目的 二次の判別関数を使った判別分析を行う。 (R の MASS パッケージに qda, predict.qda がある) 使用法 quad.disc(data, group, func.name=c("solve", "ginv")) print.quad.disc(obj, digits=5) summary.quad.disc(obj, digits=5) plot.quad.disc(obj, which=c("boxplot", "barplot", "scatterplot"), nclass=20, pch=1:obj$ngroup, col=1:obj$ngroup, xpos="topright", ypos=NULL, ...) 引数 data データ行列(行がケース,列が変数) group 各ケースがどの群であるかを表す変数 func.name 逆行列を計算する関数名(solve か ginv)。 普通に逆行列が求まる場合にはどちらを使っても結果は同じ 省略時は solve ムーア・ペンローズ型一般化逆行列を使うときは ginv obj quad.disc 関数が返すオブジェクト digits 結果の表示桁数 which 2 群判別の場合に,描画するグラフの種類 nclass barplot のときのおよその階級数 pch scatterplot を描く記号 col scatterplot の記号の色 xpos, ypos scatterplot の凡例の位置 ... boxplot, barplot, scatterplot に引き渡す引数 ソース インストールは,以下の 1 行をコピーし,R コンソールにペーストする source("http://aoki2.si.gunma-u.ac.jp/R/src/quad_disc.R", encoding="euc-jp") # 二次の判別関数 quad.disc <- function( data, # 説明変数データ行列 group, # グループを表すベクトル func.name=c("solve", "ginv")) # 逆行列を求める関数 { inverse <- if (match.arg(func.name) == "solve") solve else { library(MASS); ginv} data <- as.data.frame(data) if (is.null(colnames(data))) { colnames(data) <- paste("Var", 1:p, sep="") } vname <- colnames(data) group <- as.factor(as.matrix(group)) # 群を表す変数は factor にする OK <- complete.cases(data, group) # 欠損値を持つケースを除く data <- as.matrix(data[OK,]) group <- group[OK] p <- ncol(data) # 説明変数の個数 n <- nrow(data) # データの個数 n.i <- table(group) # 各群の例数 g.name <- names(n.i) # 群の名前 k <- length(n.i) # 群の個数 group.means <- matrix(unlist(by(data, group, colMeans)), p) # 各群・各変数の平均 vars <- array(unlist(by(data, group, var)), c(p, p, k)) # 各群の分散・共分散行列 inv.vars <- array(apply(vars, 3, inverse), c(p, p, k)) # 各群の分散・共分散行列の逆行列 scores <- sapply(1:k, function(i) { # 各ケースの各群からの距離 temp <- t(data)-group.means[,i]; sapply(1:n, function (j) temp[,j]%*%inv.vars[,,i]%*%temp[,j]) } ) p.values <- pchisq(scores, p, lower.tail=FALSE) # 各ケースが各群に属する確率 prediction <- as.factor(g.name[apply(p.values, 1, order)[k,]]) # どの群に属するか判別 correct <- ifelse(prediction == group, TRUE, FALSE) # 判別が正しいか? correct.table <- table(group, prediction) # 判別結果概括表 correct.rate <- sum(diag(correct.table))/n*100 # 正判別率 # add names colnames(group.means) <- colnames(scores) <- colnames(p.values) <- dimnames(vars)[[3]] <- dimnames(inv.vars)[[3]] <- g.name colnames(vars) <- rownames(vars) <- colnames(inv.vars) <- rownames(inv.vars) <- rownames(group.means) <- vname rownames(scores) <- rownames(p.values) <- paste("case", 1:n) return(structure(list(group.means=group.means, vars=vars, inv.vars=inv.vars, scores=scores, p.values=p.values, prediction=prediction, correct=correct, correct.table=correct.table, correct.rate=correct.rate, group=group, ngroup=k), class="quad.disc")) } # print メソッド print.quad.disc <- function( obj, # quad.disc 関数が返すオブジェクト digits=5) # 結果の表示桁数 { cat("\n判別結果\n\n") print(obj$correct.table) cat(sprintf("\n正判別率 = %.1f %%\n", obj$correct.rate)) } # summary メソッド # すべての結果を表示する summary.quad.disc <- function( obj, # quad.disc が返すオブジェクト digits=5) # 結果の表示桁数 { print.default(obj, digits=digits) } # plot メソッド plot.quad.disc <- function( obj, # quad.disc 関数が返すオブジェクトの which=c("boxplot", "barplot", "scatterplot"), # 箱髭図か棒グラフか散布図かの選択 nclass=20, # barplot の場合のおよその階級数 pch=1:obj$ngroup, # scatterplot を描く記号 col=1:obj$ngroup, # scatterplot の記号の色 xpos="topright", ypos=NULL, # scatterplot の凡例の位置 ...) # boxplot, barplot, plot に引き渡す引数 { if (obj$ngroup == 2) { group <- obj$group score <- obj$score[,1]-obj$score[,2] which <- match.arg(which) if (which == "boxplot") { # boxplot plot(score ~ group, xlab="群", ylab="二乗距離の差", ...) } else if (which == "barplot") { # barplot tbl <- table(group, cut(score, breaks=pretty(score, n=nclass))) barplot(tbl, beside=TRUE, legend=TRUE, xlab="二乗距離の差", ...) } else { # scatterplot 各群の重心までの二乗距離 group <- obj$group group.levels <- levels(group) score1 <- obj$score[,1] score2 <- obj$score[,2] max1 <- max(score1) max2 <- max(score2) max0 <- max(max1, max2) plot(score1, score2, col=col[as.integer(group)], pch=col[as.integer(group)], xlim=c(0, max0), xlab=paste(group.levels[1], "の重心への二乗距離"), ylim=c(0, max0), ylab=paste(group.levels[2], "の重心への二乗距離"), asp=1, ...) abline(0, 1, lty=2) text(max1, max2/2, paste(group.levels[2], "に判別される領域"), pos=2) text(0, max2+strheight("H")*1.5, paste(group.levels[1], "に判別される領域"), pos=4) legend(x=xpos, y=ypos, legend=group.levels, col=col, pch=pch) } } else { warning("3群以上の場合にはグラフ表示は用意されていません") } } 使用例 data(iris) # Fisher のアヤメのデータ result <- quad.disc(iris[1:4], iris[5]) # quad.disc 関数からの出力は自動的には出力されないので注意 result # 結果を出力する 出力結果例 > (result <- quad.disc(iris[1:4], iris[5]) ) # print による結果出力 判別結果 prediction group setosa versicolor virginica setosa 50 0 0 versicolor 0 47 3 virginica 0 0 50 正判別率 = 98.0 % > summary(result) # summary による結果出力 $group.means # 各群ごとの平均値 setosa versicolor virginica Sepal.Length 5.006 5.936 6.588 Sepal.Width 3.428 2.770 2.974 Petal.Length 1.462 4.260 5.552 Petal.Width 0.246 1.326 2.026 $vars # 各群の分散・共分散行列 , , setosa Sepal.Length Sepal.Width Petal.Length Petal.Width Sepal.Length 0.124249 0.099216 0.0163551 0.0103306 Sepal.Width 0.099216 0.143690 0.0116980 0.0092980 Petal.Length 0.016355 0.011698 0.0301592 0.0060694 Petal.Width 0.010331 0.009298 0.0060694 0.0111061 , , versicolor Sepal.Length Sepal.Width Petal.Length Petal.Width Sepal.Length 0.266433 0.085184 0.182898 0.055780 Sepal.Width 0.085184 0.098469 0.082653 0.041204 Petal.Length 0.182898 0.082653 0.220816 0.073102 Petal.Width 0.055780 0.041204 0.073102 0.039106 , , virginica Sepal.Length Sepal.Width Petal.Length Petal.Width Sepal.Length 0.404343 0.093763 0.303290 0.049094 Sepal.Width 0.093763 0.104004 0.071380 0.047629 Petal.Length 0.303290 0.071380 0.304588 0.048824 Petal.Width 0.049094 0.047629 0.048824 0.075433 $inv.vars # 各群の分散・共分散行列の逆行列 , , setosa Sepal.Length Sepal.Width Petal.Length Petal.Width Sepal.Length 18.9434 -12.4048 -4.5002 -4.7761 Sepal.Width -12.4048 15.5705 1.1111 -2.1041 Petal.Length -4.5002 1.1111 38.7762 -17.9350 Petal.Width -4.7761 -2.1041 -17.9350 106.0459 , , versicolor Sepal.Length Sepal.Width Petal.Length Petal.Width Sepal.Length 9.5028 -3.6762 -8.6317 6.4545 Sepal.Width -3.6762 19.7110 2.1160 -19.4803 Petal.Length -8.6317 2.1160 19.8038 -26.9372 Petal.Width 6.4545 -19.4803 -26.9372 87.2448 , , virginica Sepal.Length Sepal.Width Petal.Length Petal.Width Sepal.Length 10.5339 -3.4797 -9.9601 1.7882 Sepal.Width -3.4797 15.8754 1.1027 -8.4729 Petal.Length -9.9601 1.1027 13.4058 -2.8909 Petal.Width 1.7882 -8.4729 -2.8909 19.3141 $scores # ユークリッドの二乗距離 setosa versicolor virginica case 1 0.44911 114.80449 182.93591 case 2 2.08109 83.31536 153.97495 case 3 1.28434 94.92043 160.49415 case 4 1.70621 82.77880 140.64139 case 5 0.76169 120.48102 184.03695 case 6 3.71265 120.48007 183.29809 【中略】 case 147 578.01838 23.36413 4.00770 case 148 618.18551 16.74095 1.11181 case 149 720.69230 33.20289 3.94189 case 150 550.78799 10.11250 2.69108 $p.values # 各群への所属の確率 setosa versicolor virginica case 1 9.7826e-01 6.8699e-24 1.7457e-38 case 2 7.2085e-01 3.4538e-17 2.8628e-32 case 3 8.6403e-01 1.1849e-19 1.1454e-33 case 4 7.8959e-01 4.4882e-17 2.0574e-29 case 5 9.4351e-01 4.2162e-25 1.0126e-38 case 6 4.4629e-01 4.2181e-25 1.4594e-38 【中略】 case 147 8.8576e-124 1.0709e-04 4.0497e-01 case 148 1.7956e-132 2.1703e-03 8.9239e-01 case 149 1.1523e-154 1.0855e-06 4.1393e-01 case 150 6.9093e-118 3.8575e-02 6.1078e-01 $prediction # 判別結果 [1] setosa setosa setosa setosa setosa [6] setosa setosa setosa setosa setosa [11] setosa setosa setosa setosa setosa [16] setosa setosa setosa setosa setosa [21] setosa setosa setosa setosa setosa [26] setosa setosa setosa setosa setosa [31] setosa setosa setosa setosa setosa [36] setosa setosa setosa setosa setosa [41] setosa setosa setosa setosa setosa [46] setosa setosa setosa setosa setosa [51] versicolor versicolor versicolor versicolor versicolor [56] versicolor versicolor versicolor versicolor versicolor [61] versicolor versicolor versicolor versicolor versicolor [66] versicolor versicolor versicolor versicolor versicolor [71] virginica versicolor virginica versicolor versicolor [76] versicolor versicolor versicolor versicolor versicolor [81] versicolor versicolor versicolor virginica versicolor [86] versicolor versicolor versicolor versicolor versicolor [91] versicolor versicolor versicolor versicolor versicolor [96] versicolor versicolor versicolor versicolor versicolor [101] virginica virginica virginica virginica virginica [106] virginica virginica virginica virginica virginica [111] virginica virginica virginica virginica virginica [116] virginica virginica virginica virginica virginica [121] virginica virginica virginica virginica virginica [126] virginica virginica virginica virginica virginica [131] virginica virginica virginica virginica virginica [136] virginica virginica virginica virginica virginica [141] virginica virginica virginica virginica virginica [146] virginica virginica virginica virginica virginica Levels: setosa versicolor virginica $correct # 判別の正誤 [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [11] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [21] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [31] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [41] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [51] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [61] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [71] FALSE TRUE FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [81] TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE TRUE [91] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [101] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [111] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [121] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [131] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [141] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE $correct.table # 判別結果表 prediction group setosa versicolor virginica setosa 50 0 0 versicolor 0 47 3 virginica 0 0 50 $correct.ratio # 正判別率 [1] 98 $group [1] setosa setosa setosa setosa setosa [6] setosa setosa setosa setosa setosa [11] setosa setosa setosa setosa setosa [16] setosa setosa setosa setosa setosa [21] setosa setosa setosa setosa setosa [26] setosa setosa setosa setosa setosa [31] setosa setosa setosa setosa setosa [36] setosa setosa setosa setosa setosa [41] setosa setosa setosa setosa setosa [46] setosa setosa setosa setosa setosa [51] versicolor versicolor versicolor versicolor versicolor [56] versicolor versicolor versicolor versicolor versicolor [61] versicolor versicolor versicolor versicolor versicolor [66] versicolor versicolor versicolor versicolor versicolor [71] versicolor versicolor versicolor versicolor versicolor [76] versicolor versicolor versicolor versicolor versicolor [81] versicolor versicolor versicolor versicolor versicolor [86] versicolor versicolor versicolor versicolor versicolor [91] versicolor versicolor versicolor versicolor versicolor [96] versicolor versicolor versicolor versicolor versicolor [101] virginica virginica virginica virginica virginica [106] virginica virginica virginica virginica virginica [111] virginica virginica virginica virginica virginica [116] virginica virginica virginica virginica virginica [121] virginica virginica virginica virginica virginica [126] virginica virginica virginica virginica virginica [131] virginica virginica virginica virginica virginica [136] virginica virginica virginica virginica virginica [141] virginica virginica virginica virginica virginica [146] virginica virginica virginica virginica virginica Levels: setosa versicolor virginica $ngroup [1] 3
二群のときには,二群の重心への距離の差を求め,グラフを描く > (result <- quad.disc(iris[51:150, 1:4], iris[51:150, 5])) 判別結果 prediction group versicolor virginica versicolor 47 3 virginica 0 50 正判別率 = 97.0 % > plot(result) > plot(result, which="barplot") > plot(result, which="s", xpos="right") 解説ページ