Rでデータ分析!モザイクプロットのエラーとトラブルシューティング完全ガイド

2025-05-27

モザイクプロットとは?

モザイクプロットは、カテゴリカルデータ(名義尺度や順序尺度など、質的なデータ)のクロス集計表(分割表)を視覚的に表現するためのグラフです。特に、複数のカテゴリカル変数間の関係性を直感的に理解するのに役立ちます。

棒グラフや積み上げ棒グラフでは、通常1つまたは2つのカテゴリ変数に限定されますが、モザイクプロットはそれ以上のカテゴリ変数にも対応し、各カテゴリの組み合わせの度数を「タイルの面積」で表現します。

モザイクプロットの機能的特徴

  1. タイルの面積が度数に対応: モザイクプロットでは、グラフ全体を構成する各「タイル」の面積が、対応するクロス集計表のセルの度数(観測値の数)に比例します。これにより、どのカテゴリの組み合わせが最も多いか、または少ないかを一目で把握できます。

  2. 階層的な分割: プロットは、指定された変数の順序に従って、長方形が再帰的に垂直または水平に分割されて作成されます。例えば、最初の変数で全体を分割し、次にその分割された領域を2番目の変数でさらに分割…というように、階層的に表示されます。この分割の順序を変えることで、異なる視点からデータを見ることができます。

  3. 条件付き割合の可視化: 各タイルの幅や高さは、対応するカテゴリの条件付き割合を示します。例えば、変数をAとBで分割する場合、Aの各カテゴリの幅はAの周辺割合を示し、その中でBの各カテゴリの高さは、Aの各カテゴリにおけるBの条件付き割合を示します。

  4. 残差の表現 (shadeオプション): mosaicplot() 関数には shade = TRUE オプションがあり、これはカテゴリ間の独立性のモデルからの「ずれ」(残差)をタイルの色や網掛けで表現する機能です。

    • 独立性の仮説よりも観測された度数が高い(期待されるよりも頻繁に発生している)場合は、通常、青や緑などの色で示されます。
    • 独立性の仮説よりも観測された度数が低い(期待されるよりも稀に発生している)場合は、通常、赤などの色で示されます。
    • 色の濃淡や網掛けのパターンで、そのずれの大きさや統計的有意性を示すこともできます。これにより、どのカテゴリの組み合わせが独立性から大きく逸脱しているか(つまり、強い関連があるか)を視覚的に特定できます。

Rでの基本的な使い方

Rのgraphicsパッケージにmosaicplot()関数が用意されています。

# 例として、Rにデフォルトで用意されているHairEyeColorデータセットを使用します
# このデータセットは、髪の色(Hair)、目の色(Eye)、性別(Sex)の3つのカテゴリ変数で構成されています。

# データを読み込む
data("HairEyeColor")

# 基本的なモザイクプロット
mosaicplot(HairEyeColor, main = "髪の色、目の色、性別のモザイクプロット")

# 変数の順序を変更する例
# 目の色 -> 髪の色 -> 性別の順で分割
mosaicplot(~ Eye + Hair + Sex, data = HairEyeColor, main = "目の色、髪の色、性別のモザイクプロット")

# 残差を色で表現する例 (shade = TRUE)
mosaicplot(HairEyeColor, shade = TRUE, main = "残差表示付きモザイクプロット")

# 色をカスタマイズする例
mosaicplot(HairEyeColor, color = TRUE, main = "色分けされたモザイクプロット")
mosaicplot(HairEyeColor, color = c("lightcoral", "lightblue", "lightgreen", "gold"), main = "カスタムカラーのモザイクプロット")

# オフセット(タイルの間の隙間)を調整する例
mosaicplot(HairEyeColor, off = 5, main = "オフセットを調整したモザイクプロット")

mosaicplot()はRの標準機能ですが、より柔軟なオプションや高度な機能を提供するために、vcd (Visualizing Categorical Data) パッケージのmosaic()関数がよく使われます。vcdパッケージのmosaic()は、より詳細なグラフィックのカスタマイズや、対数線形モデルとの関連付けなど、幅広い機能を提供します。



Error in table(...) : all arguments must have the same length

このエラーは、mosaicplotに与えるデータが、クロス集計表(テーブル)の形式になっていないか、あるいは変数がデータフレーム内で同じ長さを持っていない場合に発生します。mosaicplotは基本的に、事前に作成されたテーブルオブジェクトか、複数のカテゴリカル変数を指定して内部でテーブルを作成することを想定しています。

原因:

  • table()関数に与える引数が適切でない。
  • 入力がデータフレームの場合、各列(変数)の行数が異なる。

解決策:

  • table()関数で集計する: データフレームが適切な形式であれば、mosaicplot(table(df$var1, df$var2)) のように、事前にtable()関数で集計してから渡すのが最も確実です。
    # df_correct を使ってテーブルを作成し、プロット
    my_table <- table(df_correct$Category1, df_correct$Category2)
    mosaicplot(my_table, main = "Using a Table Object")
    
  • データフレームを使用する場合: データフレームの各列(変数)が同じ行数であることを確認してください。通常、モザイクプロットに使用するデータは、各観測が1行にまとまった「長い形式」のデータフレームであるべきです。
    # 例:不適切なデータ
    df_wrong <- data.frame(
      Category1 = c("A", "B", "A"),
      Category2 = c("X", "Y") # 長さが異なる
    )
    # mosaicplot(Category1 ~ Category2, data = df_wrong) # エラーになる
    
    # 解決策:適切なデータフレーム
    df_correct <- data.frame(
      Category1 = c("A", "B", "A", "B", "A", "B"),
      Category2 = c("X", "Y", "X", "Y", "X", "Y")
    )
    mosaicplot(~ Category1 + Category2, data = df_correct,
               main = "Correct Dataframe Example")
    

Error in structure(.Data, class = "table", dim = d, dimnames = if (is.null(dn <- ...) または Error in plot.window(...) : need finite 'xlim' values

これは、データに欠損値(NA)が含まれている場合によく発生します。mosaicplotは完全なデータセットを期待するため、NAがあると処理が中断されることがあります。

原因:

  • 入力データ(データフレームまたはテーブル)にNA値が含まれている。

解決策:

  • table()useNAオプションを使用する: table()関数を使う場合は、useNA = "ifany"useNA = "always" オプションを使ってNAをカテゴリとして含めることもできます。ただし、その場合プロットの見栄えや解釈に注意が必要です。
    my_table_with_na <- table(df_with_na$Category1, df_with_na$Category2, useNA = "ifany")
    mosaicplot(my_table_with_na, main = "NA as a category")
    
  • 欠損値の除去: na.omit()関数などを使用して、欠損値を含む行をデータから削除します。
    df_with_na <- data.frame(
      Category1 = c("A", "B", NA, "B"),
      Category2 = c("X", "Y", "X", "Y")
    )
    
    # 欠損値を含む行を削除
    df_clean <- na.omit(df_with_na)
    mosaicplot(~ Category1 + Category2, data = df_clean, main = "After NA removal")
    

プロットの表示がおかしい、ラベルが重なる、または表示されない

これはエラーメッセージが出るわけではありませんが、プロットの視覚的な問題でよく遭遇します。特に変数のカテゴリ数が多い場合や、ラベルが長い場合に発生しやすいです。

原因:

  • 変数の順序が不適切。
  • プロット領域が小さい。
  • ラベルが長い。
  • カテゴリ数が多い。

解決策:

  • vcdパッケージの利用: vcdパッケージのmosaic()関数は、標準のmosaicplot()よりもラベルの配置やカスタマイズオプションが豊富です。
    # install.packages("vcd") # 必要であればインストール
    library(vcd)
    
    # vcd::mosaic() はより柔軟なオプションを持つ
    vcd::mosaic(~ Hair + Eye + Sex, data = HairEyeColor,
                gp = gpar(fill = "lightblue"), # タイルの色を統一
                labeling = labeling_border(rot_labels = c(FALSE, TRUE, FALSE, TRUE)), # ラベルの回転を細かく制御
                main = "Mosaic plot using vcd package")
    
  • オフセットの調整: off引数でタイル間の隙間を調整できます。値を大きくすると隙間が広がり、小さくすると狭まります。
    mosaicplot(HairEyeColor, off = 5, main = "Adjusted Offset")
    
  • 変数の順序の変更: mosaicplot()は、フォーミュラで指定された変数の順序でデータを分割します。順序を変えることで、プロットの見栄えや解釈が改善されることがあります。
    # Sex -> Eye -> Hair の順で分割
    mosaicplot(~ Sex + Eye + Hair, data = HairEyeColor, main = "Changed Order")
    
  • ラベルの調整: lasオプションでラベルの向きを変更したり、cexでフォントサイズを小さくしたりします。
    mosaicplot(HairEyeColor, main = "Rotate labels", las = 2, cex = 0.8) # las=2 で垂直に
    
  • プロット領域の拡大: RStudioを使用している場合は、プロットペインのサイズを大きくしてみるか、png()pdf()などのグラフィックデバイスを使ってファイルに出力することで、より大きな解像度でプロットを生成できます。
    png("mosaicplot_high_res.png", width = 800, height = 600)
    mosaicplot(HairEyeColor, shade = TRUE, main = "High Resolution Mosaic Plot")
    dev.off()
    

Error: 'x' must be an array or a table

このエラーは、mosaicplot()関数に、テーブルや配列以外のデータ形式(例えば、数値ベクトルや文字列ベクトル)が直接渡された場合に発生します。

原因:

  • mosaicplot(my_vector) のように、カテゴリカル変数自体を直接渡している。

解決策:

  • フォーミュラ構文を使用する: データフレーム内の変数を使用する場合は、フォーミュラ構文(例: ~ var1 + var2, var1 ~ var2)を使用します。
    my_df <- data.frame(
      Color = c("Red", "Blue", "Red", "Green", "Blue"),
      Size = c("Small", "Large", "Small", "Medium", "Large")
    )
    mosaicplot(~ Color + Size, data = my_df, main = "Using Formula")
    
  • 集計されたテーブルを渡す: 複数のカテゴリカル変数から作成したtableオブジェクトを渡します。
    # 悪い例:
    # my_data <- c("A", "B", "A", "C", "B")
    # mosaicplot(my_data) # エラーになる
    
    # 良い例:
    data_vector1 <- c("Red", "Blue", "Red", "Green", "Blue")
    data_vector2 <- c("Small", "Large", "Small", "Medium", "Large")
    my_table <- table(data_vector1, data_vector2)
    mosaicplot(my_table, main = "From vectors to table")
    

Error in UseMethod("mosaic") : no applicable method for 'mosaic' applied to an object of class "formula" (vcdパッケージの場合)

vcdパッケージのmosaic()関数を使用しているときに発生する可能性があります。特に、vcdパッケージが読み込まれていないか、別のパッケージに同名の関数が存在し、そちらが優先されている場合に起こりえます。

原因:

  • mosaic()という名前の関数が他のパッケージにも存在し、名前の競合が起きている。
  • vcdパッケージがlibrary()で読み込まれていない。

解決策:

  • パッケージ名を明示する: 名前空間を明示的に指定することで、どのパッケージの関数を使うかをRに指示できます。
    vcd::mosaic(~ Hair + Eye + Sex, data = HairEyeColor)
    
  • vcdパッケージの読み込み: 必ずlibrary(vcd)を実行してパッケージを読み込んでください。
    # install.packages("vcd") # 必要であればインストール
    library(vcd)
    mosaic(~ Hair + Eye + Sex, data = HairEyeColor)
    
  • オンラインで検索する: エラーメッセージをそのままGoogle検索すると、Stack Overflowなどのフォーラムで同じ問題に遭遇した人々の解決策が見つかることが非常に多いです。
  • Rのバージョンを確認する: Rやパッケージのバージョンが古いと、一部の機能が期待通りに動作しないことがあります。必要に応じてRやパッケージを最新版に更新してください。
  • 小さなデータセットで試す: 問題のコードが複雑なデータセットでうまくいかない場合、ごくシンプルなダミーデータを作成して試してみると、問題の原因を特定しやすくなります。
  • データの構造を確認する: str(), summary(), class(), dim() といった関数を使って、入力データの構造、型、次元などを確認します。
    str(HairEyeColor)
    class(HairEyeColor)
    summary(HairEyeColor)
    


基本的なモザイクプロット

最も基本的なmosaicplotの使用例です。Rに組み込まれているHairEyeColorデータセットを使用します。これは、髪の色、目の色、性別のクロス集計表です。

# 1. 基本的なモザイクプロット
# HairEyeColorデータセットを読み込む
data("HairEyeColor")

# 髪の色(Hair)と目の色(Eye)の関係をプロット
# デフォルトでは最初の2変数が使用される
mosaicplot(HairEyeColor,
           main = "髪の色と目の色の関係 (基本)",
           xlab = "髪の色",
           ylab = "目の色")

# 結果: 髪の色と目の色の組み合わせごとの頻度をタイルの面積で示します。
# 最初の変数(Hair)が横軸の分割に、次の変数(Eye)が縦軸の分割に影響します。

フォーミュラを使ったモザイクプロット

データフレーム形式のデータを使う場合、フォーミュラ(~ var1 + var2 + ...)を使って変数を指定するのが一般的です。

# 2. フォーミュラを使ったモザイクプロット
# irisデータセット(カテゴリカルにするため加工)
data("iris")
iris_cat <- iris
# Sepal.Length をカテゴリ変数に変換(例として単純に2つに分ける)
iris_cat$Sepal.Length_Cat <- ifelse(iris_cat$Sepal.Length > median(iris_cat$Sepal.Length), "Long", "Short")
# Species も既にカテゴリ変数

mosaicplot(~ Species + Sepal.Length_Cat, data = iris_cat,
           main = "IrisデータにおけるSpeciesとSepal.Length_Cat",
           color = TRUE) # 色分けを追加

# 結果: 'Species'ごとに'Sepal.Length_Cat'の分布が視覚化されます。
# 'color=TRUE'は、各タイルの最後の変数のカテゴリを異なる色で示します。

変数の順序と色のカスタマイズ

モザイクプロットでは、フォーミュラで指定する変数の順序がプロットの構造に大きく影響します。また、color引数で色を細かく設定できます。

# 3. 変数の順序と色のカスタマイズ
# HairEyeColorデータを再び使用

# 性別 -> 目の色 -> 髪の色の順でプロット
mosaicplot(~ Sex + Eye + Hair, data = HairEyeColor,
           main = "変数の順序を変更 (Sex -> Eye -> Hair)",
           color = c("red", "blue", "green", "purple")) # カスタムカラーを指定

# 結果: 最初に性別で大きく2分割され、その中で目の色、髪の色が分割されます。
# カスタムカラーは、最後の変数のカテゴリに順に適用されます。
# 指定した色の数がカテゴリ数より少ない場合、色がリサイクルされます。

残差の表示 (shade = TRUE)

カテゴリカル変数間に統計的に有意な関連があるかどうかを視覚的に判断するために、残差(独立性からのずれ)を色で表現する機能です。

# 4. 残差の表示 (`shade = TRUE`)
# HairEyeColorデータを使用

mosaicplot(HairEyeColor,
           shade = TRUE, # 残差を色で表示
           main = "残差表示付きモザイクプロット",
           cex.axis = 0.8) # 軸ラベルのフォントサイズを調整

# 結果:
# 青系の色: 独立性の仮説よりも観測値が期待値より多い(正の関連がある)
# 赤系の色: 独立性の仮説よりも観測値が期待値より少ない(負の関連がある)
# 色の濃淡は、ずれの大きさ(標準化残差の絶対値)を示します。
# これにより、特定の髪の色と目の色の組み合わせに強い関連があるかを一目で確認できます。

vcdパッケージを使った高度なモザイクプロット

vcd (Visualizing Categorical Data) パッケージは、mosaicplotよりもはるかに柔軟で豊富なオプションを提供します。より複雑なカスタマイズや統計モデルとの連携が可能です。

# 5. vcdパッケージを使った高度なモザイクプロット
# install.packages("vcd") # vcdパッケージがインストールされていない場合は実行
library(vcd)

# HairEyeColorデータを使用

# 基本的なvcd::mosaic
vcd::mosaic(~ Hair + Eye + Sex, data = HairEyeColor,
            main = "vcd::mosaicによるプロット")

# 残差表示と凡例付き
vcd::mosaic(~ Hair + Eye + Sex, data = HairEyeColor,
            shade = TRUE,
            legend = TRUE, # 凡例を表示
            gp = gpar(fill = c("grey", "lightblue", "lightgreen")), # タイルのデフォルト色
            labeling = labeling_border(rot_labels = c(FALSE, TRUE, FALSE, TRUE)), # ラベルの回転を細かく制御
            main = "vcd::mosaic (shade=TRUE, legend=TRUE)")

# 結果: vcd::mosaicは、より洗練された描画と、
# ラベルの配置、色、凡例の表示など、多くのオプションを提供します。
# 特に `labeling` 引数は、ラベルの重なりを避けるのに役立ちます。

自分で作成したデータフレームを使ってモザイクプロットを作成する例です。

# 6. カスタムデータを使った例
# 架空の調査データ
survey_data <- data.frame(
  Gender = sample(c("Male", "Female"), 100, replace = TRUE, prob = c(0.45, 0.55)),
  Education = sample(c("High School", "University", "Graduate"), 100, replace = TRUE, prob = c(0.3, 0.5, 0.2)),
  Opinion = sample(c("Agree", "Disagree", "Neutral"), 100, replace = TRUE, prob = c(0.4, 0.3, 0.3))
)

# クロス集計表を作成
# Gender と Opinion の関係
gender_opinion_table <- table(survey_data$Gender, survey_data$Opinion)
print(gender_opinion_table)

mosaicplot(gender_opinion_table,
           main = "性別と意見のモザイクプロット",
           color = TRUE,
           las = 1) # x軸ラベルを水平に

# Gender, Education, Opinion の関係
mosaicplot(~ Gender + Education + Opinion, data = survey_data,
           main = "性別、学歴、意見のモザイクプロット",
           shade = TRUE)

# 結果: 自分で作成したカテゴリカルデータの関係性を視覚的に分析できます。
# 残差表示を使用することで、どの組み合わせに統計的な関連があるかを探ることができます。


棒グラフ / 積み上げ棒グラフ (Bar Plot / Stacked Bar Plot)

最も基本的で広く使われる方法です。1つまたは2つのカテゴリ変数の度数や割合を視覚化するのに適しています。

  • 欠点: 3つ以上の変数を同時に表現するのは難しい。
  • 利点: 解釈が非常に容易。
  • 用途: 単一変数のカテゴリ分布、または2変数間の条件付き分布。

<!-- end list -->

# 例: 髪の色と目の色の積み上げ棒グラフ
data("HairEyeColor")
# HairEyeColorはテーブルオブジェクトなので、そのままではggplot2で扱いにくい
# データフレームに変換する
hec_df <- as.data.frame(HairEyeColor)

library(ggplot2)

# 髪の色ごとの目の色の分布
ggplot(hec_df, aes(x = Hair, y = Freq, fill = Eye)) +
  geom_bar(stat = "identity", position = "fill") + # position="fill"で割合を表示
  labs(title = "髪の色と目の色の割合(積み上げ棒グラフ)",
       x = "髪の色",
       y = "割合",
       fill = "目の色") +
  theme_minimal()

# 性別ごとの髪の色の分布
ggplot(hec_df, aes(x = Sex, y = Freq, fill = Hair)) +
  geom_bar(stat = "identity", position = "stack") + # position="stack"で度数を表示
  labs(title = "性別ごとの髪の色の度数(積み上げ棒グラフ)",
       x = "性別",
       y = "度数",
       fill = "髪の色") +
  theme_minimal()

並行集合プロット (Parallel Sets Plot)

複数のカテゴリ変数間の複雑な関係を、各変数のカテゴリを「層」とし、それらを接続する「帯」の幅で度数を示すことで表現します。モザイクプロットよりも変数の順序による影響を受けにくく、データの流れを直感的に把握しやすい場合があります。

  • 欠点: 非常に多くのカテゴリや変数があると、複雑になりすぎる。
  • 利点: データの流れが分かりやすい、変数の順序を自由に設定可能。
  • 用途: 3つ以上のカテゴリ変数間の関連性の探索、グループ間のフローの可視化。
# 例: HairEyeColorデータでの並行集合プロット
# install.packages("ggalluvial") # 必要であればインストール
library(ggalluvial)

# データフレームをalluvial形式(長い形式)に変換
# HairEyeColor は既にfreqの列を持つデータフレームなので、そのまま使える
hec_alluvial <- as.data.frame(HairEyeColor)

ggplot(hec_alluvial,
       aes(axis1 = Hair, axis2 = Eye, axis3 = Sex, y = Freq)) +
  geom_alluvium(aes(fill = Eye), alpha = 0.7) +
  geom_stratum() +
  geom_text(stat = "stratum", aes(label = after_stat(stratum)), size = 3) +
  scale_x_discrete(limits = c("Hair", "Eye", "Sex"), expand = c(0.15, 0.05)) +
  labs(title = "髪の色、目の色、性別の並行集合プロット",
       y = "度数") +
  theme_minimal() +
  theme(axis.text.y = element_blank(), axis.ticks.y = element_blank())

アソシエーションプロット (Association Plot)

これはmosaicplotの派生形のようなもので、カテゴリ変数間の独立性からのずれ(残差)を直接棒グラフで表現します。mosaicplot(shade=TRUE)と似た情報を、より定量的な視点から提供します。

  • 欠点: 2変数に限定されることが多く、生データ(度数)の全体像は分かりにくい。
  • 利点: 残差の大きさや方向(正の関連か負の関連か)が明確。
  • 用途: 2つのカテゴリ変数間の関連性の強さを評価する。独立性の仮説からの逸脱を強調する。
# 例: HairとEyeのアソシエーションプロット
# install.packages("vcd") # 必要であればインストール
library(vcd)

# HairEyeColorからHairとEyeの2次元テーブルを抽出
hair_eye_table <- margin.table(HairEyeColor, margin = c(1, 2))

assoc(hair_eye_table,
      main = "髪の色と目の色のアソシエーションプロット",
      gp = gpar(fill = "lightblue"), # 棒の色
      shade = TRUE) # 有意な残差を色分け

# 結果: 各カテゴリの組み合わせについて、期待度数からの標準化残差が棒グラフで表示されます。
# 青は期待より多い、赤は期待より少ないことを示し、色の濃淡は残差の大きさを表します。

ドットプロット (Dot Plot) / 蜂群プロット (Beeswarm Plot) / ジッタープロット (Jitter Plot)

カテゴリカル変数と連続変数の関係、またはカテゴリカル変数の分布を個々のデータポイントで示す場合に有効です。特に、少数カテゴリのデータ点を明確に表示したい場合に役立ちます。

  • 欠点: データポイントが多いと、描画が非常に密になる。
  • 利点: 生のデータポイントの分布を直接見ることができる。
  • 用途: 各カテゴリ内のデータポイントの分布や密集度を見る。オーバラップを避けつつ、個々のデータ点を表現する。
# 例: irisデータでSpeciesごとのSepal.Lengthの分布をドットプロットで
library(ggplot2)

ggplot(iris, aes(x = Species, y = Sepal.Length)) +
  geom_jitter(width = 0.2, alpha = 0.6, color = "darkblue") + # ジッターで点をずらす
  labs(title = "Iris SpeciesごとのSepal.Length (ジッタープロット)",
       x = "種",
       y = "がく片の長さ") +
  theme_minimal()

# geom_dotplot (ggplot2) や geom_beeswarm (ggbeeswarmパッケージ) も同様の目的で使えます。

カテゴリ変数間の独立性の検定結果をグラフィカルに表示する方法です。具体的なプロットの種類としてはアソシエーションプロットに近いですが、統計的有意性をより強く意識した表現になります。

  • 欠点: 度数そのものの分布は直接的には分かりにくい。
  • 利点: 統計的な関連性の有無と方向を明確に示す。
  • 用途: 2つ以上のカテゴリ変数間の独立性検定結果を視覚的に伝える。
# 例: HairEyeColorの独立性検定と視覚化(vcd::assocplotがこれに近い)
# カイ二乗検定の実行
chi_sq_test <- chisq.test(HairEyeColor)
print(chi_sq_test)

# このテスト結果を直接プロットする特定の汎用関数は少ないが、
# vcd::mosaic(shade=TRUE)やvcd::assoc()がその視覚化に対応する
# 例えば、vcd::assoc()は標準化残差をプロットし、p値に応じて色分けできる

mosaicplotはカテゴリカルデータの探索的データ分析に非常に強力ですが、データの量、変数の数、そして分析の目的に応じて、棒グラフ、並行集合プロット、アソシエーションプロット、または点群プロットなど、他の可視化手法も検討することで、より効果的にデータを伝えることができます。