コレスポンデンス分析の同時布置図は本当に使えないのか?(点と点の距離の話)

前回、前々回のコレスポンデンス分析についての話を目にした何人かから、「そもそもコレポンの同時布置図を点の距離で解釈しちゃいけないなんて聞いてない。どうしてダメなのか教えてほしい。」という声をいただきました。

bob3.hatenablog.com

bob3.hatenablog.com

「どうしてダメなのか?」を数学的に説明するのは私には無理なので、朝野先生による解説などを参照していただきたいです。

今回は「実際、コレポンの同時布置図では点の距離で行と列の関係を表現できていないのでダメです。」という話をします。

サンプルデータは前回も使った日経リサーチさんのデータを引用させていただきます。

dat <- c(
  18, 43, 175, 249, 52, 133, 78, 34, 93, 40, 207, 165, 108, 35, 78, 23, 115, 97, 30, 52,
  124, 248, 59, 29, 48, 19, 113, 75, 165, 161, 24, 25, 47, 177, 36, 126, 16, 38, 21, 11,
  36, 48, 101, 97, 86, 63, 50, 57, 50, 54, 58, 35, 43, 63, 42, 45, 37, 53, 32, 49,
  51, 284, 26, 15, 7, 6, 52, 11, 110, 144, 10, 17, 27, 118, 20, 87, 8, 9, 4, 10,
  284, 7, 452, 188, 76, 25, 177, 223, 181, 19, 156, 39, 272, 86, 52, 85, 28, 85, 185, 318,
  60, 2, 265, 100, 72, 55, 64, 66, 33, 10, 115, 45, 111, 20, 32, 12, 39, 48, 62, 123,
  85, 4, 329, 132, 79, 51, 94, 105, 67, 27, 118, 32, 121, 47, 32, 42, 25, 72, 94, 182,
  189, 40, 233, 36, 27, 16, 80, 176, 107, 19, 57, 24, 88, 73, 13, 67, 7, 49, 89, 104,
  106, 112, 87, 20, 16, 11, 63, 60, 55, 65, 24, 10, 43, 69, 10, 43, 8, 31, 38, 26,
  37, 297, 31, 23, 14, 14, 60, 20, 102, 94, 24, 14, 19, 87, 26, 71, 4, 21, 6, 10,
  148, 28, 197, 46, 25, 21, 70, 151, 80, 10, 78, 22, 67, 55, 16, 53, 12, 43, 73, 73,
  77, 100, 159, 81, 32, 26, 118, 125, 126, 22, 110, 25, 81, 77, 29, 78, 15, 79, 48, 45,
  352, 40, 253, 18, 24, 13, 125, 203, 164, 111, 30, 22, 177, 184, 12, 98, 14, 79, 119, 152,
  24, 240, 58, 120, 44, 117, 95, 18, 125, 87, 76, 88, 69, 55, 96, 67, 161, 61, 17, 24,
  42, 16, 149, 42, 41, 38, 30, 37, 13, 8, 58, 30, 49, 18, 10, 12, 28, 29, 28, 43,
  168, 121, 140, 75, 50, 35, 140, 97, 184, 98, 39, 25, 88, 157, 30, 153, 57, 68, 64, 77,
  72, 155, 106, 43, 25, 27, 64, 42, 113, 59, 49, 19, 48, 77, 13, 71, 18, 48, 39, 36,
  49, 155, 74, 24, 34, 27, 59, 35, 64, 63, 27, 17, 28, 66, 20, 47, 18, 30, 23, 18
) |>
  matrix(
    nrow = 18,
    byrow = TRUE,
    dimnames = list(
      Brands = LETTERS[1:18],
      Attributes = c(
        "伝統や格式を重んじる", "庶民的", "価格が高い",
        "流行を作り出している", "価値上昇", "新鮮味", "顧客の心つかんでいる",
        "気品を感じさせる", "ファン層幅広い", "機能性重視", "デザイン重視",
        "既成概念囚れない", "存在感", "ずっと付合っていける",
        "社会動きに敏感", "誰からも好かれる", "躍動感",
        "さりげなく特徴をアピール", "豊かな気持ちにさせる", "自慢になる"
      )
    )
  )

まず、コレスポンデンス分析で表そうとしている行と列の関係はクロス集計表の残差であるとします。

残差は実測値と期待値との差であり、期待値通りでない部分に行と列の関係が現れます。

ただ、この残差はサンプルサイズの影響を受けるので、何らかの方法で標準化する必要があります。

これが指標化残差です。

n <- sum(dat) # 総度数(n)
P <- dat/n # 観測割合(P)
row.masses <- rowSums(P) # 行質量(row masses、平均列プロファイル)
column.masses <- colSums(P) # 列質量(column masses)
E <- row.masses %o% column.masses # 期待値
R <- P - E # 残差
I <- R / E # 指標化残差

この指標化残差が同時布置図上で行の点と列の点の距離として表現できていればいいはずです。

確認してみましょう。

まずはコレスポンデンス分析を実行し、同時布置図上の座標を取得します。フレンチプロット、非対称プロット、対称バイプロットの3パターンで確認します。

library(ca)
res.ca <- ca(dat)

map_symm <- plot(res.ca, map = "symmetric")
map_rowpr <- plot(res.ca, map = "rowprincipal")
map_symbi <- plot(res.ca, map = "symbiplot")

行の点と列の点の距離はdist()関数で取得できます。

dist_symm <- rbind(map_symm$rows, map_symm$cols) |> dist()
vec_symm <- as.matrix(dist_symm)[1:18, 19:38] |> as.vector()

dist_rowpr <- rbind(map_rowpr$rows, map_rowpr$cols) |> dist()
vec_rowpr <- as.matrix(dist_rowpr)[1:18, 19:38] |> as.vector()

dist_symbi <- rbind(map_symbi$rows, map_symbi$cols) |> dist()
vec_symbi <- as.matrix(dist_symbi)[1:18, 19:38] |> as.vector()

あとは、指標化残差とこれらの距離の関係を散布図で確認します。 何らかの比例関係が認められれば、距離で指標化残差が表現できているといえるはずです。

Iv <- I |> as.vector()

par(mfrow=c(2,2)) 
plot(Iv, vec_symm, main="フレンチプロット", pch=21, col = "#0000ff", bg="#0000ff33",
     xlab="標準化残差", ylab="行の点と列の点の距離")
plot(Iv, vec_rowpr, main="非対称プロット", pch=21, col = "#0000ff", bg="#0000ff33",
     xlab="標準化残差", ylab="行の点と列の点の距離")
plot(Iv, vec_symbi, main="対称バイプロット", pch=21, col = "#0000ff", bg="#0000ff33",
     xlab="標準化残差", ylab="行の点と列の点の距離")

f:id:bob3:20220127215451p:plain
距離と標準化残差の散布図

一定の相関はあるものの、やはり距離で行と列の関係を表せているとはいいがたいようです。

というわけで、コレポンの同時布置図における行と列の関係は、距離ではなく、角度(方向)と長さで解釈した方が良いようです