こんにちは、usagi-sanです。今回は教育用標準データセットSSDSE-2020B.csvを用いて、複数のデータセットを用いたデータ整形の練習をしていきます。
データセットを複数に分割したり、分割されたデータフレームを併合したりしていきます。
また、複数のデータセットの集計方法として、多元分割表の作成の仕方もみていきます。
また、今回用いるプログラミングコードも以下からダウンロード可能です。
R言語 データフレーム分割併合・多元分割表 Rスクリプト
練習用としてぜひぜひダウンロードしてください。
0815 ソースコードに間違いがあったので修正しました。
また、データフレームの操作をすべてまとめた記事も書きました。データフレームの詳細については次の記事を参照。
【R言語】データフレーム操作 作成・値の代入・行と列の追加と削除など
R言語を使う際に避けては通れない道であるデータフレームの操作について解説します。 データフレーム(data.frame)はデータセットを格納するための行列であり、データ解析をするうえで必要不可欠です。 ...
続きを見る
準備
データセットの読み込み
複数のデータセットを用意するために、まず解析するデータをread.csvを用いて読み込みます。
1 2 | #データセットの読み込み df <- read.csv("SSDSE-2020B.csv", fileEncoding = "CP932") |
教育用標準データセットSSDSE-2020B.csvには、"Year"という列名があるため、年度別のデータセットをまず作成します(年度別のデータセットの入手が難しいため、1つのデータセットを複数のデータセットに分割しています)。次のようにdfの一部を参照すると、"Year"があるのが分かります。このleves別のデータセットを準備として作成します。
年度別データセットの作成
次のコードを実行し、年度別のデータセットを作成しましょう。
1 2 3 4 5 6 7 8 9 | #データセットを年度別のデータに分割する year <- levels(as.factor(df[2:nrow(df),"Year"])) for(i in 1:length(year)){ tmp <- NULL tmp <- df[df[,"Year"] == year[i] , setdiff(colnames(df), "Year")] tmp <- rbind(df[1, setdiff(colnames(df), "Year")], tmp) write.csv(tmp, paste0("SSDSE-2020B_", year[i] ,"_.csv"), row.names = F, fileEncoding = "CP932") } |
年度別のデータには"Year"という年度の列は必要ないため、上のfor文中で列を省いています。
では早速、年度別のデータセットを読み込んでみましょう。
1 2 3 4 5 | #複数のデータセットをリストに格納する dfList <- NULL for(i in 1:length(year)){ dfList[[i]] <- read.csv(paste0("SSDSE-2020B_", year[i], "_.csv"), fileEncoding = "CP932") } |
複数のファイルを読み込みたいときは、1行目のdfListようにリストに格納すると便利です。
年度別データのリストdfListの1つ目の要素には2006年のデータが入っているのが確認できます。同様に2007年、2008年、… のデータがdfListに格納されています。
1 2 3 4 5 6 7 8 9 10 11 12 | > dfList[[1]][1:10,1:5] Code Prefecture A1101 A110101 1 地域コード 都道府県 総人口 総人口(男) 2 R01000 北海道 5605000 2661000 3 R02000 青森県 1424000 672000 4 R03000 岩手県 1375000 658000 5 R04000 宮城県 2358000 1147000 6 R05000 秋田県 1134000 535000 7 R06000 山形県 1207000 580000 8 R07000 福島県 2080000 1011000 9 R08000 茨城県 2974000 1480000 10 R09000 栃木県 2016000 1002000 |
これで、1つのデータセットから年度別の複数のデータセットを作成することができました。
次に複数のデータセットを併合する方法について紹介します。
複数のデータフレームの併合
列名Yearの挿入
まず、dfListの各要素の列名には、年度を表すものがないため、各データフレームに"Year"という列を挿入します。
次を実行し、dfListの各データフレームに"Year"という列を追加しましょう。"Year"の列の要素には対応する年を代入しています。
1 2 3 4 | #列名Yearを挿入 for(i in 1:length(dfList)){ dfList[[i]] <- data.frame(Code = dfList[[i]][, 1], Year = c("年度", rep(year[i], nrow(dfList[[i]])-1)), dfList[[i]][, 2:ncol(dfList[[i]])]) } |
上のfor文の中のように、データフレームにベクトルを挿入する場合はdata.frameなどを用いるとよいです。挿入する列を適切な位置に挟んで結合させます(cbindを用いても同様に挿入することができます)。
データフレームの併合
年度別のデータフレームを併合させ、元のSSDSE-2020B.csvの形に整えていきます。
データフレームの併合については以前の記事データフレーム練習で紹介した通り、関数mergeやrbindを用いることで可能です。
まず関数mergeを用いたデータフレームの併合方法を説明します。
次のようにmerge(データフレームA, データフレームB, all =T)とすることで2つのデータフレームA、Bを併合させることができます。
1 2 3 4 5 6 7 8 | #データフレームの併合 #merge用いた例 tmp <- dfList[[1]][numeric(0),] for(i in 1:length(dfList)){ tmp <- merge(tmp, dfList[[i]][2:nrow(dfList[[i]]),], all = T) } df <- rbind(dfList[[1]][1,], tmp) |
次にrbindを用いた方法は以下の通りです。
rbind(データフレームA, データフレームB)とすることで2つのデータフレームA、Bを行方向に結合させることができます。
1 2 3 4 5 6 | #rbindを用いた例 tmp <- dfList[[1]][numeric(0),] for(i in 1:length(dfList)){ tmp <- rbind(tmp, dfList[[i]][2:nrow(dfList[[i]]),]) } df <- rbind(dfList[[1]][1,], tmp) |
注意として、mergeとrbindも列名を紐づけしている点です。
そのため、違う列名を持つデータフレームを併合または結合させるときには注意が必要です。
データフレームdfを参照してみましょう。
次のように、"Year"に2006年から2020年までのlevelsを含むデータフレームを作成することができました。
1 2 3 4 5 6 7 8 9 10 11 12 | > df[1:10,1:5] Code Year Prefecture A1101 A110101 1 地域コード 年度 都道府県 総人口 総人口(男) 2 R01000 2006 北海道 5605000 2661000 3 R02000 2006 青森県 1424000 672000 4 R03000 2006 岩手県 1375000 658000 5 R04000 2006 宮城県 2358000 1147000 6 R05000 2006 秋田県 1134000 535000 7 R06000 2006 山形県 1207000 580000 8 R07000 2006 福島県 2080000 1011000 9 R08000 2006 茨城県 2974000 1480000 10 R09000 2006 栃木県 2016000 1002000 |
これだけでも十分ですが、元のSSDSE-2020B.csvと比べると都道府県でソートされていないことが分かります。
文字列のソート
次のように、都道府県の列”Prefecture”をcharacter型からfator形に変更し、そのlevelsでソートすることで都道府県でデータフレームをソートすることができます。
1 2 3 4 | #都道府県でソートする bar <- df[2:nrow(df),] tmp <- as.factor(bar[, "Prefecture"]) df <- rbind(df[1,], bar[order(as.numeric(tmp)),]) |
上の2行目では、barにdfの2行目以降を代入しています。これは1行目もデータの列名を意味するためです。
3行目でbarを、levels=c("北海道", "青森県", ... ,"沖縄県")をlevelsとするfactorに変更し、これをtmpとしています。
4行目では、dfの列名である1行目とtmpをlevelsでソートしたものをrbindで結合させています。
上のように、文字列をソートするときは関数orderを用います。
factorのlevelsをas.numericとするとlevelsの順序となるため、この順序をorderでソートすることで文字列もソートすることが可能です。
dfをみてみると、実際に都道府県でソートされたことが確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 | > df[1:10,1:5] Code Year Prefecture A1101 A110101 1 地域コード 年度 都道府県 総人口 総人口(男) 2 R01000 2006 北海道 5605000 2661000 260 R01000 2006 北海道 5605000 2661000 210 R01000 2007 北海道 5579000 2644000 212 R01000 2008 北海道 5548000 2626000 214 R01000 2009 北海道 5524000 2612000 216 R01000 2010 北海道 5506419 2603345 218 R01000 2011 北海道 5488000 2593000 220 R01000 2012 北海道 5465000 2580000 227 R01000 2013 北海道 5438000 2565000 |
write.csvで併合後のデータフレームを出力してみましょう。
1 | write.csv(df, "SSDSE2020B(併合後).csv", row.names = F, fileEncoding = "CP932") |
下の画像のように、併合前と併合後のデータが一致していることが分かります。
データフレームの併合が正しく行われていることが確認できました。
多元分割表
次に、多元分割表の作り方について説明します。
カテゴリカルデータを扱う際に、分割表は重要になってきます。
多元分割表の作り方
データフレームから多元分割表を作る際には、関数xtabsが便利です。
まず準備として、dfの列名と4列目以降のデータをas.numericで数値にします。
1 2 3 4 5 6 7 | #多元分割表 colnames(df) <- df[1,] df <- df[-1,] for(i in 4:ncol(df)){ #数値化 df[,i] <- as.numeric(df[,i]) } |
2元分割表
都道府県と年度に関する総人口の2元分割表を作ってみましょう。
次のようにして、2元分割表を作ることが可能です。
1 | table <- xtabs(総人口 ~ 都道府県 + 年度 ,data = df) |
2元分割表tableは次のようにデータフレームとなっていることが確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 | > table[1:10,1:10] 年度 都道府県 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 愛知県 14614000 7357000 7399000 7411000 7410719 7418000 7431000 7449000 7464000 7483128 愛媛県 2920000 1453000 1445000 1438000 1431493 1424000 1415000 1406000 1396000 1385262 茨城県 5948000 2973000 2971000 2970000 2969770 2960000 2947000 2937000 2927000 2916976 岡山県 3912000 1956000 1953000 1949000 1945276 1941000 1937000 1932000 1926000 1921525 沖縄県 2738000 1374000 1378000 1385000 1392818 1402000 1411000 1419000 1426000 1433566 岩手県 2750000 1364000 1352000 1340000 1330147 1315000 1306000 1299000 1290000 1279594 岐阜県 4210000 2104000 2100000 2091000 2080773 2071000 2062000 2053000 2043000 2031903 宮崎県 2300000 1146000 1141000 1138000 1135233 1130000 1125000 1119000 1112000 1104069 宮城県 4716000 2354000 2349000 2348000 2348165 2326000 2329000 2333000 2335000 2333899 京都府 5292000 2643000 2640000 2637000 2636092 2633000 2628000 2622000 2616000 2610353 |
関数xtabsの説明は、この後に説明しますが、 xtabs( ~ tab, data )のように~の前に何も指定しないと、セルの度数を返し、指定するとセルの合計を返します。
3元分割表
次に3元分割表を作ってみましょう。
まず、準備として、次の二つのカテゴリカルデータ”待機児童数カテゴリカル”、”各種学校数カテゴリカル”をdfに追加します。
1 2 3 4 5 6 | #3元分割表 bar <- cut (df[,"保育所等利用待機児童数"], breaks = c(0, mean(df[,"保育所等利用待機児童数"]), 10000) ,labels = c("0~平均", "平均~"), right = F) df <- cbind(df, 待機児童数カテゴリカル = bar) bar <- cut (df[,"各種学校数"], breaks = c(0, mean(df[,"各種学校数"]), 10000) ,labels = c("0~平均", "平均~"), right = F) df <- cbind(df, 各種学校数カテゴリカル = bar) |
多元分割表を作るには、次のようにxtabsの引数に、カテゴリカルデータの列名を追加し、関数ftableを用います。
1 2 3 | table <- xtabs(総人口 ~ 都道府県 + 各種学校数カテゴリカル + 待機児童数カテゴリカル, data = df) Table <- ftable(table) |
xtabs(y ~, x1+x+2+x3, data)のように、カテゴリカルデータ分の多元分割表を作ることができます。
3行目に、関数ftaleの引数にtableをいれて実行することで、より多元分割表らしい見た目のデータフレームを作ることができます。
3元分割表Tableを参照すると、次のようになっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 | > Table 待機児童数カテゴリカル 0~平均 平均~ 都道府県 各種学校数カテゴリカル 愛知県 0~平均 0 0 平均~ 59399128 37069719 愛媛県 0~平均 18452755 0 平均~ 0 0 茨城県 0~平均 35424746 2892000 平均~ 0 0 岡山県 0~平均 21372801 3822000 平均~ 0 0 沖縄県 0~平均 0 0 平均~ 0 18241384 |
上のようなクロス集計表の作成方法については、R言語クロス集計表を参照してください。
またftableの引数にrow.varsを指定すると、表の行と列を反転させることができます。
関数xtabs
関数xtabs(formula = ~., data = parent.frame(), subset, sparse = FALSE, na.action, addNA = FALSE, exclude = if(!addNA) c(NA, NaN), drop.unused.levels = FALSE)の引数を以下にまとめました。
formula | クロス集計する式。yをx1とx2とx3で集計したい場合式y~x1+x1+x3のようにする。 | addNA | NAをカウントするかどうかを指定する |
data | データフレーム | exclude | 除外するデータ |
subset | data中で用いれるベクトルを指定する | drop.unused.levels | 用いられていないlevelsを除外する |
sparse | スパース行列とするかを指定しする | na.action | データにNAがあるときの処理を指定する関数 |
関数ftable
関数ftable(x, exclude=c(NA, NaN), row.vars = NULL, col.vars = NULL)の引数を以下にまとめました。
exclude | 分割表の集計から除くオブジェクト。初期値としてNAとNaNを除く。 |
row.vars | フラット分割表の行名 |
col.vars | フラット分割表の列名 |
まとめ
今回は、R言語で複数のデータセットを扱う方法を紹介しました。
エクセルでは難しいデータ整形でも、R言語などのプログラミングを用いれば、自在にデータを分割させたり併合させたりすることができます。
特に複数のデータセットを同時に扱いたい場合は、プログラミングを組んだ方が堅実です(エクセルでもVBAの知識があれば可能です)。