こんにちはusagi-sanです。
この記事では、R言語のデータフレームに関して重要な知識を紹介します。
データフレームの操作はデータ解析や統計解析をするうえで、絶対に必要になってくるので参考になったらうれしいです。
今回用いるプログラミングコードは下のダウンロードリンクからも入手できます。
また、データフレームの操作をすべてまとめた記事も書きました。データフレームの詳細については次の記事を参照。
-   
- 【R言語】データフレーム操作 作成・値の代入・行と列の追加と削除など- R言語を使う際に避けては通れない道であるデータフレームの操作について解説します。 データフレーム(data.frame)はデータセットを格納するための行列であり、データ解析をするうえで必要不可欠です。 ... - 続きを見る 
データフレームの練習
データフレームの操作
まず練習用のデータとして、R言語にデフォルトで入っているirisというアヤメのデータを用います。
次のコードでデータフレームirisをdataに代入します。
| 1 | data <- iris | 
次に、このデータフレームの要素を抽出していきます。
データフレームから任意のデータを抽出できるようになるまでが、最初の難関だと思います。
| 1 2 3 4 5 | data[,colnames(data)[1]] #Sepal.Lengthのデータ setdiff(colnames(data), "Species") #Species以外のデータ data[data[,"Species"] == "setosa",]#setosa種のみのデータ data2 <- data[,setdiff(colnames(data), "Species")]#Species以外のデータ | 
1行目のようにして、data[,列名]でデータフレームの列を特定の列名で指定すると、
その列名のベクトルを抽出することができます。
2行目では、dataの列名のうち"Species"以外の列名をsetdiff(データフレーム,列名)で得ています。
3行名では、列名"Speciess"が"setosa"であるデータの行を取り出しています。
5行目では2行目で指定した"Speicise"以外の列のデータフレームを取得しています。
注意として、通常データフレームはdata[a,b]やdata[a,]などで指定する場合が多いですが、
データ解析のデータを整形するときに、上記の3行目の操作をする場合が多いです。
データフレームの操作によく用いる関数
上では説明していませんでしたが、データフレームを操作するときに便利である関数を以下に使いかたとともにまとめておきました。
| 1 2 3 4 5 6 7 8 9 10 | #データフレームに用いる関数 nrow(data)  #データフレームの行数 ncol(data)  #データフレームの列数 dim(data)   #データフレームの行、列 rownames(data)  #データフレームの行名 colnames(data)  #データフレームの列名 intersect(c(1,2,3,4,5), c(3,4,5)) setdiff(c(1,2,3,4,5), c(3,4,5)) | 
下の表に関数の意味を示し、上でその使いかたを示しました。
| nrow(x) | データフレームxの行数を返す | 
| ncol(x) | データフレームxの列数を返す | 
| dim(x) | データフレームxの行数、列数を返す | 
| rownames(x) | データフレームxの行名を返す | 
| colnames(x) | データフレームxの列数を返す | 
| intersect(x,y) | ベクトルxとベクトルyの両方に含まれている要素を返す | 
| setdiff(x,y) | ベクトルxからベクトルyにある要素を取り除く | 
データフレームの結合
複数のデータフレームまたはベクトルの行方向と列方向への結合は、集計表や分割表を作る際に必須となっていきます。
R言語では以下のように、rbind(a,b),cbind(a,b)を用いることで、データフレームやベクトルを結合させることができます。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #データフレームの結合 std_Sepal.Length <- (data2$Sepal.Length - mean(data2$Sepal.Length)) / sqrt(var(data2$Sepal.Length)) data2 <- cbind(data2, std_Sepal.Length) mean_data <- round(apply(data2, 2, mean), 5) #Sepal.Length  Sepal.Width Petal.Length  Petal.Widthの平均値 var_data <- round(apply(data2, 2, var), 5) #不偏分散 data2 <- rbind(data2, mean_data, var_data) #平均、分散の行を結合する rownames(data2) <- c(1:nrow(data), "mean","var") data.frame(data$Sepal.Length, data$Petal.Length)  #data$Sepal.Length, data$Petal.Lengtからなるでーれフレームを作成 merge(data[1:50,],data2[46:100,])  #dataとdata2の共通部分を返す merge(data[1:50,],data2[46:100,], all = T)  #dataとdata2を併合する | 
2,3行目ではdata2の列名"Sepal.Length","Sepal.Width","Petal.Length","Petal.Width"の期待値と不偏分散を求めています。
関数applyについては今度、書こうと思います。
5行目では、先ほど求めた期待値のベクトル、分散のベクトルを、行方向にdata2の下に結合しています。
また7行目では、列名"Sepal.Length"を標準化したデータを求めています。"Sepal.Length"の各データから期待値を引き、分散の平方根で割ると標準化データが得られます。
9行目では、標準化データを、列方向にdata2の右に結合しています。
11行目では、data.frame(a,b)を用いてもデータフレームaとbを横方向に結合することが可能です。
13,14行目ではmerge(a,b)を使ったデータフレームの併合を紹介しています。引数allをTRUEにすることで、併合(結合)を行うことができます。引数を指定しない場合、aとbの共通する部分を返します。
以下にデータの結合に用いる関数をまとめました。
| rbind(x,y) | データフレームxとyを縦方向に結合 | 
| cbind(x,y) | データフレームxとyを横方向に結合 | 
| data.frame(x,y) | データフレームxとyを横方向に結合 | 
| merge(x,y,all=bool) | データフレームxとyを併合する。allがTRUEの場合xとyが併合される。FALSEの場合xとyの共通部分を返す | 
ベクトルの要素の並び替え
データフレームのある列の要素を昇順や降順で並び替えたい場合、sort(ベクトル)、rev(ベクトル)やorder(ベクトル)が役に立ちます。
データフレームの列のソートの例として、次のコードを書きました。
| 1 2 3 4 5 6 | #データフレームの並び替え sort(data2$Sepal.Length)  #昇順 rev(data2$Sepal.Length)   #降順 order(data2$Sepal.Length, decreasing = F)  #昇順 order(data2$Sepal.Length, decreasing = T)  #降順 | 
2行目では、データフレームのdata2のうち列名が"Sepal.Length"であるベクトルをsort(ベクトル)で昇順に並べています。
3行目では、rev(ベクトル)を用いて、降順に並べています。
5,6行目ではorder(ベクトル,真偽値)を用いた昇順、降順の例を示しました。
引数decreasingをTRUEにすることで、降順で並べることが可能となります。
以下に関数をまとめます。
| sort(x) | ベクトルx昇順に並べる | 
| rev(x) | ベクトルxを降順に並べる | 
| order(x, decreasing = bool) | ベクトルxを引数decreasingがTRUEのとき降順に、FALSEのとき昇順に並べる | 
データ整形の例
先ほどのirisのデータで分割表を作ってみましょう。
"Sepal.Length"の値が平均より大きいか小さいかと、"Species"が"setosa"かそれ以外かで分割表を作ってみます。
分割表を作ってくれる便利なライブラリもありますが、ここでは練習として今まで使った関数を用いて作成してます。
| 1 2 3 4 5 6 7 8 9 10 11 | data_11 <- data[data$Sepal.Length > as.list(mean_data)$Sepal.Length & data$Species== "setosa",] data_12 <- data[data$Sepal.Length <= as.list(mean_data)$Sepal.Length & data$Species== "setosa",] data_21 <- data[data$Sepal.Length > as.list(mean_data)$Sepal.Length & data$Species!= "setosa",] data_22 <- data[data$Sepal.Length <= as.list(mean_data)$Sepal.Length & data$Species!= "setosa",] table <- data.frame(matrix(c(nrow(data_11),nrow(data_21),nrow(data_12),nrow(data_22)), nrow =2))  rownames(table) <- c("Speciesがsetosaである","Speciesがsetosaでない") colnames(table) <- c("Sepal.Lengthが平均値より大きい","Sepal.Lengthが平均値以下") table <- rbind(table, 総計=apply(table,2,sum)) table <- cbind(table, 総計=apply(table,1,sum)) | 
上のコードを実行することで下の表の分割表を作成することができます。
1~4行目で分割表の4つの要素に当てはまるデータフレームを抽出しています。
6行目にdata_11~data_22の要素の数をデータフレームに変換し2×2の表を作っています。
8,9行目に行名、列名を指定し、10行目で、apply関数を用いて行の和をとりrbindで先ほどの2×2の表の下に結合させています。
最後に列の和をとりcbindで右に結合させることで、分割表が完成します。
| Sepal.Lengthが平均値より大きい | Sepal.Lengthが平均値以下 | 総計 | |
| Speciesがsetosaである | 0 | 50 | 50 | 
| Speciesがsetosaでない | 70 | 30 | 100 | 
| 総計 | 70 | 80 | 150 | 
