目的 二次元クロス集計表から,双対尺度法による解析を行う R の MASS ライブラリに入っている corresp 関数と同じであるが,若干親切な出力をする 使用法 dual(tbl) summary(object, nf=ncol(object), weighted=FALSE, digits=3) plot(object, first=1, second=2, weighted=FALSE) 引数 tbl 二次元クロス表を行列として与える object dual が返すオブジェクト nf いくつの解を出力するか(デフォルトは最大数) weighted 相関比で重み付けした解を対象にするかどうか(デフォルトは,重み付けしない解) digits 出力する数値の小数点以下の桁数 first 横軸に取る解の番号(デフォルトは 1) second 縦軸に取る解の番号(デフォルトは 2) color.row 行に与えられる数値を描く記号(デフォルトは "blue") color.col 列に与えられる数値を描く記号(デフォルトは "black") mark.row 行に与えられる数値を描く記号(デフォルトは 19) mark.col 列に与えられる数値を描く記号(デフォルトは 15) xlab 横座標軸名(デフォルトは paste("Axis", first, sep="-")) ylab 縦座標軸名(デフォルトは paste("Axis", second, sep="-")) axis 座標軸を点線で描くなら TRUE(デフォルトは FALSE) xcgx 横軸に取る座標の符号反転が必要なら TRUE(デフォルトは FALSE) xcgy 縦軸に取る座標の符号反転が必要なら TRUE(デフォルトは FALSE) ... points, text 等に渡されるその他の引数 ソース インストールは,以下の 1 行をコピーし,R コンソールにペーストする source("http://aoki2.si.gunma-u.ac.jp/R/src/dual.R", encoding="euc-jp") # 二次元クロス集計表・度数表を双対尺度法で分析する dual <- function(tbl) # 二次元クロス表(度数表)を行列として与える { tbl <- data.matrix(tbl) # データフレームも行列にする nr <- nrow(tbl) # 行数 nc <- ncol(tbl) # 列数 if (is.null(rownames(tbl))) { # 行ラベルの補完 rownames(tbl) <- paste("Row", 1:nr, sep="-") } if (is.null(colnames(tbl))) { # 列ラベルの補完 colnames(tbl) <- paste("Col", 1:nc, sep="-") } ft <- sum(tbl) # サンプルサイズ fr <- rowSums(tbl) # 行和 fc <- colSums(tbl) # 列和 temp <- sqrt(outer(fc, fc)) w <- t(tbl/fr)%*%tbl/temp-temp/ft res <- eigen(w) # 固有値・固有ベクトルを求める ne <- length(res$values[res$values > 1e-5]) # 有効な解の個数 vec <- res$vectors[,1:ne, drop=FALSE] # 固有ベクトルの切り詰め val <- res$values[1:ne] # 固有値の切り詰め col.score <- vec*sqrt(ft/fc) # 列スコア row.score <- tbl%*%col.score/outer(fr, sqrt(val)) # 行スコア col.score2 <- t(t(col.score)*sqrt(val)) # 相関比で重み付けした列スコア row.score2 <- t(t(row.score)*sqrt(val)) # 相関比で重み付けした列スコア cont <- val/sum(diag(w))*100 # 寄与率 chi.sq <- -(ft-1-(nr+nc-1)/2)*log(1-val) # カイ二乗値 df <- nr+nc-1-2*(1:ne) # 自由度 P <- pchisq(chi.sq, df, lower.tail=FALSE) # P 値 result <- matrix(c(val, sqrt(val), cont, cumsum(cont), chi.sq, df, P), byrow=TRUE, ncol=ne) rownames(result) <- c("eta square", "correlation", "contribution", "cumulative contribution", "Chi square value", "degrees of freedom", "P value") colnames(result) <- colnames(row.score) <- colnames(col.score) <- paste("Axis", 1:ne, sep="-") rownames(row.score) <- rownames(tbl) rownames(col.score) <- colnames(tbl) dimnames(row.score2) <- dimnames(row.score) dimnames(col.score2) <- dimnames(col.score) result <- list(result=result, row.score=row.score, column.score=col.score, row.score.weighted=row.score2, column.score.weighted=col.score2) class(result) <- c("dual") invisible(result) } インストールは,以下の 1 行をコピーし,R コンソールにペーストする source("http://aoki2.si.gunma-u.ac.jp/R/src/summary.dual.R", encoding="euc-jp") # dual クラス のための summary メソッド (dual, pc.dual, ro.dual が利用する) summary.dual <- function( x, # dual が返すオブジェクト nf=ncol(x[[1]]), # 出力する解の数 weighted=FALSE, # 相関比で重み付けした解を出力するなら TRUE digits=3) # 出力する数値の小数点以下の桁数 { suf <- if (weighted) 4 else 2 # 相関比で重み付けした解も選べる str <- if (weighted) "weighted " else "" print(round(x[[1]][, 1:nf, drop=FALSE], digits=digits)) cat(sprintf("\n%srow score\n", str)) print(round(x[[suf]][, 1:nf, drop=FALSE], digits=digits)) cat(sprintf("\n%scolumn score\n", str)) print(round(x[[suf+1]][, 1:nf, drop=FALSE], digits=digits)) } インストールは,以下の 1 行をコピーし,R コンソールにペーストする source("http://aoki2.si.gunma-u.ac.jp/R/src/plot.dual.R", encoding="euc-jp") # dual クラス のための plot メソッド (dual, pc.dual, ro.dual が利用する) plot.dual <- function( x, # dual が返すオブジェクト first=1, # 横軸にプロットする解 second=2, # 縦軸にプロットする解 weighted=FALSE, # 相関比で重み付けした解をプロットするなら TRUE color.row="blue", color.col="black", # 行と列のプロット色 mark.row=19, mark.col=15, # 行と列のプロット記号 xlab=paste("Axis", first, sep="-"), # 横座標軸名 ylab=paste("Axis", second, sep="-"), # 縦座標軸名 axis=FALSE, # 座標軸を点線で描くなら TRUE xcgx=FALSE, # 横軸に取る座標の符号反転が必要なら TRUE xcgy=FALSE, # 縦軸に取る座標の符号反転が必要なら TRUE ...) # points, text 等に渡されるその他の引数 { if (ncol(x[[1]]) == 1) { warning("解が1個しかありません。二次元配置図は描けません。") return } suf <- if (weighted) 4 else 2 # 相関比で重み付けした解も選べる old <- par(xpd=TRUE, mar=c(5.1, 5.1, 2.1, 5.1)) # 左右を大きめに空ける row1 <- x[[suf]] [, first] # 横軸に取る解 col1 <- x[[suf+1]][, first] if (xcgx) { # 必要なら符号反転 row1 <- -row1 col1 <- -col1 } row2 <- x[[suf]] [, second] # 縦軸に取る解 col2 <- x[[suf+1]][, second] if (xcgy) { # 必要なら符号反転 row2 <- -row2 col2 <- -col2 } plot(c(row1, col1), c(row2, col2), type="n", xlab=xlab, ylab=ylab, ...) points(row1, row2, pch=mark.row, col=color.row, ...) text(row1, row2, labels=names(row1), pos=3, col=color.row, ...) points(col1, col2, pch=mark.col, col=color.col, ...) text(col1, col2, labels=names(col1), pos=3, col=color.col, ...) par(old) if (axis) { # 座標軸を点線で描くならば abline(v=0, h=0, lty=3, ...) } } 使用例 tbl <- matrix(c( # 3行4列の分割表の例(ファイルから読んでも良い) 2, 3, 5, 6, 5, 1, 7, 5, 5, 3, 4, 3 ), byrow=TRUE, ncol=4) ans <- dual(tbl) summary(ans) summary(ans, weighted=TRUE) plot(ans, 1, 2) library(MASS) # R の MASS 中の corresp を使ってみる corresp(tbl, nf=min(nrow(tbl), ncol(tbl))-1) 出力結果例 > ans <- dual(tbl) > summary(ans) # 相関比で重み付けしない解を,小数点以下3桁で出力(デフォルト) Axis-1 Axis-2 eta square 0.049 0.038 correlation 0.221 0.194 contribution 56.572 43.428 cumulative contribution 56.572 100.000 Chi square value 2.263 1.727 degrees of freedom 4.000 2.000 P value 0.687 0.422 row score Axis-1 Axis-2 Row-1 -1.436 0.040 Row-2 0.665 -1.131 Row-3 0.733 1.315 column score Axis-1 Axis-2 Col-1 1.550 0.429 Col-2 -0.930 2.160 Col-3 0.116 -0.792 Col-4 -0.996 -0.542 > summary(ans, weighted=TRUE) # 相関比で重み付けした解 Axis-1 Axis-2 eta square 0.049 0.038 correlation 0.221 0.194 contribution 56.572 43.428 cumulative contribution 56.572 100.000 Chi square value 2.263 1.727 degrees of freedom 4.000 2.000 P value 0.687 0.422 weighted row score Axis-1 Axis-2 Row-1 -0.318 0.008 Row-2 0.147 -0.220 Row-3 0.162 0.255 weighted column score Axis-1 Axis-2 Col-1 0.343 0.083 Col-2 -0.206 0.419 Col-3 0.026 -0.154 Col-4 -0.221 -0.105 > plot(ans, 1, 2) # 結果の表示 > ans # print メソッドでは dual が返す全ての結果を表示する $result Axis-1 Axis-2 eta square 0.04905396 0.03765652 correlation 0.22148129 0.19405288 contribution 56.57212279 43.42787721 cumulative contribution 56.57212279 100.00000000 Chi square value 2.26340816 1.72727308 degrees of freedom 4.00000000 2.00000000 P value 0.68743886 0.42162603 $row.score Axis-1 Axis-2 Row-1 -1.4355847 0.03995533 Row-2 0.6650934 -1.13131472 Row-3 0.7331783 1.31495864 $column.score Axis-1 Axis-2 Col-1 1.5502397 0.4286333 Col-2 -0.9301824 2.1595197 Col-3 0.1158234 -0.7921783 Col-4 -0.9960553 -0.5418132 $row.score.weighted Axis-1 Axis-2 Row-1 -0.3179552 0.007753447 Row-2 0.1473057 -0.219534884 Row-3 0.1623853 0.255171517 $column.score.weighted Axis-1 Axis-2 Col-1 0.34334909 0.08317752 Col-2 -0.20601799 0.41906103 Col-3 0.02565271 -0.15372449 Col-4 -0.22060761 -0.10514041 attr(,"class") [1] "dual"
> library(MASS) > corresp(tbl, nf=min(nrow(tbl), ncol(tbl))-1) # dual 関数と比較すれば対応はすぐ分かるが,Row/Col scores は列単位に符号が逆転することがある。 # 列単位の符号の逆転は結果の解釈にはなんの影響もない。 First canonical correlation(s): 0.2214813 0.1940529 # dual 関数の出力の correl Row scores: # dual 関数の出力の $"row.score" [,1] [,2] R 1 1.4355847 -0.03995533 R 2 -0.6650934 1.13131472 R 3 -0.7331783 -1.31495864 Col scores: # dual 関数の出力の $"column.score" [,1] [,2] C 1 -1.5502397 -0.4286333 C 2 0.9301824 -2.1595197 C 3 -0.1158234 0.7921783 C 4 0.9960553 0.5418132 参考文献 西里静彦「質的データの数量化−双対尺度法とその応用−」,朝倉書店,1982