R言語を使う際に避けては通れない道であるデータフレームの操作について解説します。
データフレーム(data.frame)はデータセットを格納するための行列であり、データ解析をするうえで必要不可欠です。
この記事では、下記のデータフレームの基本的な操作:作成や値の参照・代入、行と列の追加や削除などを一通りまとめています。
この記事で学べる事
- データフレームの作成
- データフレームの参照
- データフレームの要素の取得
- データフレームの要素の変更
- 行名・列名の変更
- 行と列の追加・挿入・削除
- データフレームの結合
- データフレームの並び替え・ソート
- データフレームの転置(行と列の逆転)
- 欠測値の処理
- 行と列の合計・割合・平均・分散
- データフレームからピボットテーブルを作成
- データフレームのファイルへの保存
データ整形する際に必要な知識を網羅することができます。
この記事で扱うプログラミングコードは以下からダウンロードすることができます。テンプレートとして使ってもらって構いません。
R言語 データフレームの操作
ベクトルの操作方法については次の記事でまとめています。
【R言語】ベクトルの操作 作成・値の代入・要素の追加など
R言語のベクトルの操作(作成や参照、代入、要素の追加など)をまとめました。 この記事では以下のベクトルに関する操作を実行例付きで分かりやすく解説しています。 この記事で学べる事 ベクトルの作成 ベクト ...
続きを見る
データフレームの操作について見ていきます。作成や値の参照・代入、行と列の追加や削除だけでなくデータフレームのソートや欠測値などについてもまとめています。
実行例を全部載せた結果、ものすごい量になってしまったので複数のページに分けて操作方法を解説しています。
各ページの内容
を扱っています。
データフレームの作成
データフレームの作成するには関数data.frameを使います。
data.frameの引数を何も指定しない場合、0行0列のデータフレームのを作成することができます。
0行c列やr行0列のデータフレームする際は、関数matrixの引数nrowやncolをそれぞれrとcに指定した後に、[, 0]や[0, 1]で0列または0行の行列を作ります。この行列をdata.frameに渡すことで作成することができます。
1 2 3 4 5 6 7 8 9 10 | > #データフレームの作成 > data.frame() #0行0列のデータフレーム 0 列 0 行のデータフレーム > > data.frame(matrix(nrow = 3)[, 0]) #3行0列のデータフレーム 0 列 3 行のデータフレーム > > data.frame(matrix(ncol = 2)[0, ]) #0行2列のデータフレーム [1] X1 X2 <0 行> (または長さ 0 の row.names) |
引数にベクトルを複数並べることで、そのベクトルを列にもつデータフレームを作成することが可能です。また、行列の形を保ったままデータフレームに変換することもできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | > df1 <- data.frame(numbers = seq(1, 10), letters = letters[seq(1, 10)]) #ベクトルから作成 > df2 <- data.frame(matrix(seq(1, 10), nrow = 5)) #行列から作成 > df1 numbers letters 1 1 a 2 2 b 3 3 c 4 4 d 5 5 e 6 6 f 7 7 g 8 8 h 9 9 i 10 10 j > df2 X1 X2 1 1 6 2 2 7 3 3 8 4 4 9 5 5 10 |
データフレームの参照
データ解析をする前に、データセットがどのような変数から構成されているのか知りたいときがよくあります。
関数headとtailを用いることでデータフレームの先頭と末尾の要素を確認することが可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | > #データフレームの参照 > df1 <- data.frame(numbers = seq(1, 10), letters = letters[seq(1, 10)], + logicals = sample(c(TRUE, FALSE), 10, replace = TRUE), + dates = seq(Sys.Date(), by = "day", length.out = 10), + row.names = paste0("id:", seq(1, 10))) > head(df1) #先頭 numbers letters logicals dates id:1 1 a TRUE 2022-01-28 id:2 2 b FALSE 2022-01-29 id:3 3 c TRUE 2022-01-30 id:4 4 d FALSE 2022-01-31 id:5 5 e TRUE 2022-02-01 id:6 6 f FALSE 2022-02-02 > tail(df1) #末尾 numbers letters logicals dates id:5 5 e TRUE 2022-02-01 id:6 6 f FALSE 2022-02-02 id:7 7 g TRUE 2022-02-03 id:8 8 h FALSE 2022-02-04 id:9 9 i FALSE 2022-02-05 id:10 10 j FALSE 2022-02-06 |
また、次のように引数nを指定することで、どこまで参照するか指定することが可能です。
1 2 3 4 5 | > head(df1, 3) #位置を指定 numbers letters logicals dates id:1 1 a TRUE 2022-01-28 id:2 2 b FALSE 2022-01-29 id:3 3 c TRUE 2022-01-30 |
また、行名や列名を知りたいときはrownamesやcolnames、dimnamesを用います。以下、関数の概要です。
- rownamesで行名
- colnamesで列名
- dimnamesで行名と列名のリスト
また、次はrownamesとcolnamesの実行例です。
1 2 3 4 5 6 7 8 9 10 | > rownames(df1) #行名 [1] "id:1" "id:2" "id:3" "id:4" "id:5" "id:6" "id:7" "id:8" "id:9" "id:10" > colnames(df1) #列名 [1] "numbers" "letters" "logicals" "dates" > dimnames(df1) #次元名(行・列名) [[1]] [1] "id:1" "id:2" "id:3" "id:4" "id:5" "id:6" "id:7" "id:8" "id:9" "id:10" [[2]] [1] "numbers" "letters" "logicals" "dates" |
これらの関数を使うことでデータフレームがどのような変数から構成されているのか把握することができます。
データフレームの要素の取得
データフレームの要素の参照方法をいくつかに分けて紹介します。
後の要素の変更および代入で紹介しますが、データフレームの要素の参照には次の3通りの方法があります。
- インデックスで指定する方法
- 行名や列名で指定する方法
- 真偽値(logical型)で指定する方法
それぞれの利点を実行例とともに説明していきます。
インデックスで指定
まず、一番簡単な指定方法であるインデックスについて見ていきます。
データフレームdfの要素を参照する方法を次のリストにまとめました。
- 5行2列の要素を参照したいときは、df[5, 2]
- 3行目を取得したいときは,df[3, ]
- 3から5行目を取得したいときは、df[seq(3, 5), ]
- 2列目を取得したいときは、df[, 2]
- 1列目と2列目を取得したいときは、df[, c(1, 2)]
- 3から5行目かつ1と2行目を取得したいときは、df1[seq(3, 5), c(1, 2)]
上に示すように、行や列単位で取得したいときは、行や列に対応する要素を指定しないで参照したい行や列のインデックスを与えれば大丈夫です。
また、複数の行を取得したいときは、ベクトルを与えてあげます。
さらに、行と列にインデックスのベクトルを与えることで、データフレームのその行と列が交差する部分を取得することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | > df1 numbers letters logicals dates id:1 1 a TRUE 2022-01-28 id:2 2 b FALSE 2022-01-29 id:3 3 c TRUE 2022-01-30 id:4 4 d FALSE 2022-01-31 id:5 5 e TRUE 2022-02-01 id:6 6 f FALSE 2022-02-02 id:7 7 g TRUE 2022-02-03 id:8 8 h FALSE 2022-02-04 id:9 9 i FALSE 2022-02-05 id:10 10 j FALSE 2022-02-06 > > df1[5, 2] #5行目2列目 [1] "e" > > df1[3, ] #3行目 numbers letters logicals dates id:3 3 c TRUE 2022-01-30 > > df1[seq(3, 5), ] #3から5行目 numbers letters logicals dates id:3 3 c TRUE 2022-01-30 id:4 4 d FALSE 2022-01-31 id:5 5 e TRUE 2022-02-01 > > df1[, 2] #2列目 [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" > > df1[, c(1, 2)] #1から2列目 numbers letters id:1 1 a id:2 2 b id:3 3 c id:4 4 d id:5 5 e id:6 6 f id:7 7 g id:8 8 h id:9 9 i id:10 10 j > > df1[seq(3, 5), c(1, 2)] #3から5行目, 1から2列目 numbers letters id:3 3 c id:4 4 d id:5 5 e |
インデックスで指定するのは簡単ですが、例えば解析するデータセットの列の順番が変わったり行の順番が変わってしまうと、いちいち書き直さなければいけないという手間がかかります。
また、全てインデックスで指定してしまうとプログラミングコードがマジックナンバーだらけになってしまい、何を描いているのか分かりません。
コードの質的にもよろしくないので、インデックスで指定する方法はあまりお勧めしません。
この次に紹介する名前で指定する方法や真偽値で指定する方法をお勧めします。
行名や列名で指定
続いて行名や列名で指定する方法について見ていきます。データセットに行名や列名があれば、上のインデックスで指定する方法を頼らずにすべての操作が可能です。
名前をプログラミングコードで書いているので、どこで何の処理を行っているのかパッと見分かりやすく、インデックスよりおススメです。この指定方法に慣れましょう。
行名や列名でデータフレームの要素を参照する方法を以下にまとめます。
- 行名"id:1"の行かつ列名"letters"を参照したいときは、df["id:1", "letters"]
- 行名"id:1"の行を取得したいときは、df["id:1", ]
- 行名"id:1"から"id:5"の行を取得したいときは、df[paste0("id:", seq(1, 5)), ]
- 列名"letters"の列を取得したいときは、df[, "letters"]
- 行名"id:1"から"id:5"の行かつ列名"numbers"と"letters"の列を取得したいときは、df[paste0("id:", seq(1, 5)), c("numbers", "letters")]
- 3から5行目かつ1と2行目を取得したいときは、df1[seq(3, 5), c(1, 2)]
インデックスのように参照したい行名や列名を与えることで参照が可能です。行名や列名1つのみでなく、ベクトルを与えることで複数の行と列を取得することもできます。
列に関してはdf$lettersのように、データフレームの後ろに$を付けて列を取得することもできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | > #名前で取得 > df1["id:1", ] #行 numbers letters logicals dates id:1 1 a TRUE 2022-01-28 > > df1$numbers #列 [1] 1 2 3 4 5 6 7 8 9 10 > > df1[, "numbers"] #列 [1] 1 2 3 4 5 6 7 8 9 10 > > df1["id:5", "letters"] #行名id:5かつ列名letters [1] "e" > > df1[paste0("id:", seq(1, 5)), ] #1から5行目 numbers letters logicals dates id:1 1 a TRUE 2022-01-28 id:2 2 b FALSE 2022-01-29 id:3 3 c TRUE 2022-01-30 id:4 4 d FALSE 2022-01-31 id:5 5 e TRUE 2022-02-01 > > df1[, c("numbers", "letters")] #1と2列目 numbers letters id:1 1 a id:2 2 b id:3 3 c id:4 4 d id:5 5 e id:6 6 f id:7 7 g id:8 8 h id:9 9 i id:10 10 j > > df1[paste0("id:", seq(1, 5)), c("numbers", "letters")] #1から5行目かつ1と2列目 numbers letters id:1 1 a id:2 2 b id:3 3 c id:4 4 d id:5 5 e |
真偽値で指定
データフレームのある条件を満たす要素を参照したいときに、真偽値で指定する方法が凄い便利です。
logical型のベクトルをデータフレームの大括弧の行と列に入れることで、logical型のTRUEの部分が交差する要素を参照することができます。何を言っているのか分からないと思うので、次の具体例で説明します。
2行目と3行目でlogical型のベクトルを与えています。データフレームのこのベクトルを与えると、1から5行目かつ1列目と2列目を取得することができました。
1 2 3 4 5 6 7 8 9 10 | > #真偽値で取得 > rows_logical <- c(TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) > cols_logical <- c(TRUE, TRUE, FALSE, FALSE) > df1[rows_logical, cols_logical] numbers letters id:1 1 a id:2 2 b id:3 3 c id:4 4 d id:5 5 e |
このようにTRUEであるインデックスの要素を参照することができます。これを用いることで次の特定の条件を満たすデータフレームの要素の参照が可能になります。この真偽値による指定は、例えばデータフレームにnumeric型の変数があって、「ある数値に等しい」または「a以上b以下」である行を取得したい場合に重宝します。
- 列numbersが5である行を取得したいときは、df[df$numbers == 5, ]
- numbersが3から7かつlettersが"d"または"f"である行を取得するときは、df[df1$numbers >= 3 & df1$numbers <= 7 & df1$letters == "d" | df1$letters == "f", ]
- 列名が"logicals"でない列を取得したいときは、df1[, colnames(df1) != "logicals"]
- 列名に"l"が含まれる列を取得するときは、df1[, grepl("l", colnames(df1))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | > df1[df1$numbers == 5, ] #numbersが5の行 numbers letters logicals dates id:5 5 e TRUE 2022-02-01 > > df1[df1$numbers >= 3 & df1$numbers <= 7, ] #numbersが3から7までの行 numbers letters logicals dates id:3 3 c TRUE 2022-01-30 id:4 4 d FALSE 2022-01-31 id:5 5 e TRUE 2022-02-01 id:6 6 f FALSE 2022-02-02 id:7 7 g TRUE 2022-02-03 > > df1[df1$numbers >= 3 & df1$numbers <= 7 & df1$letters == "d" | df1$letters == "f", ] #numbersが3から7かつlettersが"d"または"f"の行 numbers letters logicals dates id:4 4 d FALSE 2022-01-31 id:6 6 f FALSE 2022-02-02 > > df1[, colnames(df1) != "logicals"] #"logicals"でない列 numbers letters dates id:1 1 a 2022-01-28 id:2 2 b 2022-01-29 id:3 3 c 2022-01-30 id:4 4 d 2022-01-31 id:5 5 e 2022-02-01 id:6 6 f 2022-02-02 id:7 7 g 2022-02-03 id:8 8 h 2022-02-04 id:9 9 i 2022-02-05 id:10 10 j 2022-02-06 > > df1[, grepl("l", colnames(df1))] #列名に"l"が含まれる列 letters logicals id:1 a TRUE id:2 b FALSE id:3 c TRUE id:4 d FALSE id:5 e TRUE id:6 f FALSE id:7 g TRUE id:8 h FALSE id:9 i FALSE id:10 j FALSE |