ここでは、読み込んだデータを整形したり加工したりするのによく使う関数を紹介します。なお、ここではデータフレームを念頭においています。
説明で使用するデータフレームとして、Rにもともと組み込まれているiris
データを使用します。
names(iris)
## [1] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width"
## [5] "Species"
str(iris)
## 'data.frame': 150 obs. of 5 variables:
## $ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
## $ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
## $ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
## $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
## $ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
head(iris)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5.0 3.6 1.4 0.2 setosa
## 6 5.4 3.9 1.7 0.4 setosa
データフレーム内の要素へアクセス(選択・指定)する方法を紹介します。これが基本かつ最重要です。
データハンドリングは「操作したいターゲットを指定」することが第一歩となります。操作したいターゲットを指定できるのであれば、あとはそれを処理してしまえばいいのです。逆にこれができないと何もできないこととなります。Excelなどと違い、Rは関数で指定していくため、最初に躓くポイントです。
行番号を指定してアクセスするには、以下のようにやります:
iris[3,] # 3行目(全部)にアクセス
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 3 4.7 3.2 1.3 0.2 setosa
データフレーム名のすぐ後に角括弧[,]
をつけ、その中で数値を指定するとその要素へアクセスできます。[行,列]
とイメージしてください。
列番号を指定してアクセスするには、以下のような感じになります:
x <- iris[, 2] # irisの2列目にアクセス
head(x, 5) # 長いので上から5つ分取り出す
## [1] 3.5 3.0 3.2 3.1 3.6
考え方は行番号で説明したのと同様です。もちろん両方同時に指定してアクセスもできます:
iris[3, 2] # 20行目の2列目にアクセス
## [1] 3.2
まずは行と列になれましょう。
iris[21:24,] # 21行目から24行目へアクセス
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 21 5.4 3.4 1.7 0.2 setosa
## 22 5.1 3.7 1.5 0.4 setosa
## 23 4.6 3.6 1.0 0.2 setosa
## 24 5.1 3.3 1.7 0.5 setosa
行番号を:
でつなぐと連番を持ってきます。なお、この:
は数値の連番が入ったベクトルを返す演算子です:
3:8
## [1] 3 4 5 6 7 8
つまり、[ , ]
では数値ベクトルを与えればその数値にアクセスしてくれるのです:
x <- iris[, c(2,5)] # 2列目と5列目へアクセス
head(x, 5) # 長いので5行分
## Sepal.Width Species
## 1 3.5 setosa
## 2 3.0 setosa
## 3 3.2 setosa
## 4 3.1 setosa
## 5 3.6 setosa
c(2,5)
は2
と5
がはいった数値ベクトルなので、2列目と5列目にアクセスするようになります。
もちろん、両方を同時に指定できます:
iris[21:24, c(2, 5)]
## Sepal.Width Species
## 21 3.4 setosa
## 22 3.7 setosa
## 23 3.6 setosa
## 24 3.3 setosa
「ある要素を除外する」という場合には、-
を活用します:
iris[21:24,-5] # 21-24行目から、5列目を除外
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## 21 5.4 3.4 1.7 0.2
## 22 5.1 3.7 1.5 0.4
## 23 4.6 3.6 1.0 0.2
## 24 5.1 3.3 1.7 0.5
行番号や列番号は正の整数しか存在しないため、-
を負の値とはみなさす、このように処理してくれるんだと思います。:
を使った連番では以下のようになります:
iris[21:24,-4:-5] # 21-24行目から4,5列目を除外
## Sepal.Length Sepal.Width Petal.Length
## 21 5.4 3.4 1.7
## 22 5.1 3.7 1.5
## 23 4.6 3.6 1.0
## 24 5.1 3.3 1.7
-4:-5
は-4と
-5`が入った数値ベクトルを返してくるため、その2つが効果を発揮します。なお、数値ベクトルを準備してそれを除外することもできます:
iris[21:24, -c(2, 5)] #21-24行目から2列目と5列目を除外
## Sepal.Length Petal.Length Petal.Width
## 21 5.4 1.7 0.2
## 22 5.1 1.5 0.4
## 23 4.6 1.0 0.2
## 24 5.1 1.7 0.5
おそらくは最後の例を基本に考えていたほうがいいでしょう。
通常、列番号ではなく変数名(列名)を使うことが多いかと思います。この場合、以下のように指定します:
x <- iris$Sepal.Width # irisのSepal.Widthにアクセス
head(x, 3) # 上から3行分
## [1] 3.5 3.0 3.2
データフレーム名$変数名
で指定可能です。なおRStudioなら、この$
を入力したら候補が出てきますので、選択が楽になるはずです。もしデータフレーム内の変数リストがほしい時はls()
関数が便利です:
ls(iris) #iris内の変数(オブジェクト)リストを出力
## [1] "Petal.Length" "Petal.Width" "Sepal.Length" "Sepal.Width"
## [5] "Species"
subset()
関数を使ってアクセスsubset()
はデータフレームから切り出してサブデータセットを作るイメージです。[ , ]
で説明したような内容をスムーズに行なえます。
x <- subset(iris, select = 2:3) # irisから2:3列目を選択
head(x, 3) # xの3行分
## Sepal.Width Petal.Length
## 1 3.5 1.4
## 2 3.0 1.4
## 3 3.2 1.3
subset()
関数の第一引数にデータフレームを指定し、select=
引数で列を指定します。考え方は上述の[,]
と同様です。
x <- subset(iris, select = Sepal.Width) #irisからSepal.Widthを選択
head(x, 3)
## Sepal.Width
## 1 3.5
## 2 3.0
## 3 3.2
selectに変数名を直接指定することも可能です。文字列("Sepal.Width"
のようなもの)でもOKです。複数の列名を指定してアクセスも可能です:
x <- subset(iris, select = c(Sepal.Length,Sepal.Width))
head(x, 3)
## Sepal.Length Sepal.Width
## 1 5.1 3.5
## 2 4.9 3.0
## 3 4.7 3.2
このように、select=
にベクトルでもOKとなります。また、変数が並んでいるときなどは、以下のように:
を使うこともできます:
x <- subset(iris, select = Sepal.Length:Petal.Length)
head(x, 3)
## Sepal.Length Sepal.Width Petal.Length
## 1 5.1 3.5 1.4
## 2 4.9 3.0 1.4
## 3 4.7 3.2 1.3
irisデータはSepal.Lengthが1列目、Petal.Lengthは3行目にあるので、1列目から3列目まで持ってくるようになります。使いドコロとしては、心理尺度などでs101
からs110
までの変数が並んでいる場合、以下のようにアクセスすることが可能となります:
# hogeというデータフレームにs101からs110まで並んで入っているとします
subset(hoge, select = s101:s110)
また、除外する変数を変数名で指定することも可能です。考え方は[,]
と同様で-
を利用します:
x <- subset(iris, select = -c(Sepal.Length,Species))
head(x, 2)
## Sepal.Width Petal.Length Petal.Width
## 1 3.5 1.4 0.2
## 2 3.0 1.4 0.2
これで除外できます。なお、指定する変数名は文字列ベクトルで与えることができるので、こんな感じで準備することもできます:
select_list1 <- paste("se", c(1, 3, 5, 8, 10), sep = "")
select_list1
## [1] "se1" "se3" "se5" "se8" "se10"
あるいは正規表現を使って、以下のように指定することもできたりします:
# ls(iris)でiris内の変数名を取得し、その中から「冒頭に"S"がある」ものを持ってくる
x <- subset(iris, select = grep("^S", ls(iris)))
head(x, 3)
## Petal.Length Petal.Width Species
## 1 1.4 0.2 setosa
## 2 1.4 0.2 setosa
## 3 1.3 0.2 setosa
このあたりは結構応用的で難しく感じるかもしれません。そのうちでいいと思います。
条件を指定して、レコードを抽出することができます:
subset(iris, subset = Sepal.Width>4.0)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 16 5.7 4.4 1.5 0.4 setosa
## 33 5.2 4.1 1.5 0.1 setosa
## 34 5.5 4.2 1.4 0.2 setosa
subset = (条件式)
で、その条件にマッチするレコード(行)にアクセスします。この場合、「Sepal.Widthが4より大きい行」を抽出してきます。もちろん上述の列を指定するselect=
と同時に使えます:
subset(iris, select = 2:3, subset = Sepal.Width>4.0)
## Sepal.Width Petal.Length
## 16 4.4 1.5
## 33 4.1 1.5
## 34 4.2 1.4
以上は>=
で、以下は<=
が演算子となります:
subset(iris, subset = Sepal.Width>=4.0)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 15 5.8 4.0 1.2 0.2 setosa
## 16 5.7 4.4 1.5 0.4 setosa
## 33 5.2 4.1 1.5 0.1 setosa
## 34 5.5 4.2 1.4 0.2 setosa
「~と等しい」という場合には==
が演算子となります:
x <- subset(iris, subset = Species=="setosa")
head(x)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5.0 3.6 1.4 0.2 setosa
## 6 5.4 3.9 1.7 0.4 setosa
「と等しくない(ではない)」という場合は、!=
が演算子となります:
x <- subset(iris, subset = Species!="setosa")
x[sample(nrow(x), size = 10),] #ランダムに10行持ってくる
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 140 6.9 3.1 5.4 2.1 virginica
## 107 4.9 2.5 4.5 1.7 virginica
## 99 5.1 2.5 3.0 1.1 versicolor
## 131 7.4 2.8 6.1 1.9 virginica
## 52 6.4 3.2 4.5 1.5 versicolor
## 115 5.8 2.8 5.1 2.4 virginica
## 136 7.7 3.0 6.1 2.3 virginica
## 67 5.6 3.0 4.5 1.5 versicolor
## 82 5.5 2.4 3.7 1.0 versicolor
## 143 5.8 2.7 5.1 1.9 virginica
もし、「AまたはBのどちらかとマッチするもの」を取り出したい場合、%in%
演算子を使います:
x <- subset(iris, subset = Species %in% c("setosa", "versicolor"))
x[sample(nrow(x), size = 10),] #ランダムに10行持ってくる
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 25 4.8 3.4 1.9 0.2 setosa
## 21 5.4 3.4 1.7 0.2 setosa
## 76 6.6 3.0 4.4 1.4 versicolor
## 30 4.7 3.2 1.6 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 15 5.8 4.0 1.2 0.2 setosa
## 89 5.6 3.0 4.1 1.3 versicolor
## 82 5.5 2.4 3.7 1.0 versicolor
## 33 5.2 4.1 1.5 0.1 setosa
## 22 5.1 3.7 1.5 0.4 setosa
条件が複数ある場合、ANDなら&でつなぎ、ORなら|でつなぎます:
subset(iris, subset = Sepal.Width>3.5 & Petal.Width>1.0)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 110 7.2 3.6 6.1 2.5 virginica
## 118 7.7 3.8 6.7 2.2 virginica
## 132 7.9 3.8 6.4 2.0 virginica
subset(iris, subset = Sepal.Width>4.0 | Petal.Width>2.0)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 16 5.7 4.4 1.5 0.4 setosa
## 33 5.2 4.1 1.5 0.1 setosa
## 34 5.5 4.2 1.4 0.2 setosa
## 101 6.3 3.3 6.0 2.5 virginica
## 103 7.1 3.0 5.9 2.1 virginica
## 105 6.5 3.0 5.8 2.2 virginica
## 106 7.6 3.0 6.6 2.1 virginica
## 110 7.2 3.6 6.1 2.5 virginica
## 113 6.8 3.0 5.5 2.1 virginica
## 115 5.8 2.8 5.1 2.4 virginica
## 116 6.4 3.2 5.3 2.3 virginica
## 118 7.7 3.8 6.7 2.2 virginica
## 119 7.7 2.6 6.9 2.3 virginica
## 121 6.9 3.2 5.7 2.3 virginica
## 125 6.7 3.3 5.7 2.1 virginica
## 129 6.4 2.8 5.6 2.1 virginica
## 133 6.4 2.8 5.6 2.2 virginica
## 136 7.7 3.0 6.1 2.3 virginica
## 137 6.3 3.4 5.6 2.4 virginica
## 140 6.9 3.1 5.4 2.1 virginica
## 141 6.7 3.1 5.6 2.4 virginica
## 142 6.9 3.1 5.1 2.3 virginica
## 144 6.8 3.2 5.9 2.3 virginica
## 145 6.7 3.3 5.7 2.5 virginica
## 146 6.7 3.0 5.2 2.3 virginica
## 149 6.2 3.4 5.4 2.3 virginica
文字列の部分一致も以下のように実行すればできます:
x <- subset(iris, subset = grepl("sa", iris$Species))
x[sample(nrow(x), 10),]
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 25 4.8 3.4 1.9 0.2 setosa
## 34 5.5 4.2 1.4 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 16 5.7 4.4 1.5 0.4 setosa
## 48 4.6 3.2 1.4 0.2 setosa
## 1 5.1 3.5 1.4 0.2 setosa
## 35 4.9 3.1 1.5 0.2 setosa
## 41 5.0 3.5 1.3 0.3 setosa
## 24 5.1 3.3 1.7 0.5 setosa
## 46 4.8 3.0 1.4 0.3 setosa
詳細は省略します。。
既存の変数に処理をして、他の変数へ出す場合は、transform()
関数を使用します:
x <- transform(iris, kazu=Sepal.Width+5)
head(x,3)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species kazu
## 1 5.1 3.5 1.4 0.2 setosa 8.5
## 2 4.9 3.0 1.4 0.2 setosa 8.0
## 3 4.7 3.2 1.3 0.2 setosa 8.2
第一引数に元となるデータフレーム、以降に新しい変換した変数を定義します。
先の新しい変数名を、既存の変数名にすると、その変数が上書きされて更新されます:
x <- transform(x, kazu=Sepal.Width+5)
基本、「元に戻す」という機能はないので、こういうデータハンドリングはコードをスクリプトに残すようにして履歴をたどれるようにしておいてください。
サンプルとして、以下のデータフレームを準備します:
## x1 y1
## 1 1 11
## 2 2 12
## 3 3 NA
## 4 NA 14
## 5 5 15
このデータフレームからNAを含む行を削除するには、以下のようにします:
x[complete.cases(x),]
## x1 y1
## 1 1 11
## 2 2 12
## 5 5 15
分析に使う関数によっては、na.rm=
という引数が使えることもあるので、各関数のヘルプを確認してください。
行和(横方向へ足し算)するときは、rowSums()
関数を使用します:
x <- subset(iris, select = -Species)
head(x)
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1 5.1 3.5 1.4 0.2
## 2 4.9 3.0 1.4 0.2
## 3 4.7 3.2 1.3 0.2
## 4 4.6 3.1 1.5 0.2
## 5 5.0 3.6 1.4 0.2
## 6 5.4 3.9 1.7 0.4
head(rowSums(x))
## 1 2 3 4 5 6
## 10.2 9.5 9.4 9.4 10.2 11.4
多くの場合、そのデータフレームに新たな列として追加したいでしょうから、以下のような感じになります:
x$rsum <- rowSums(x)
head(x)
## Sepal.Length Sepal.Width Petal.Length Petal.Width rsum
## 1 5.1 3.5 1.4 0.2 10.2
## 2 4.9 3.0 1.4 0.2 9.5
## 3 4.7 3.2 1.3 0.2 9.4
## 4 4.6 3.1 1.5 0.2 9.4
## 5 5.0 3.6 1.4 0.2 10.2
## 6 5.4 3.9 1.7 0.4 11.4
上のx$rsum
のように、存在しない変数に対してベクトルを放り込むと、新しくその変数(列)が作られます。
行平均を算出するときは、rowMeans()
関数を利用します。使い方はrowSums()
と同様です:
x <- subset(iris, select = -Species)
head(x)
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1 5.1 3.5 1.4 0.2
## 2 4.9 3.0 1.4 0.2
## 3 4.7 3.2 1.3 0.2
## 4 4.6 3.1 1.5 0.2
## 5 5.0 3.6 1.4 0.2
## 6 5.4 3.9 1.7 0.4
head(rowMeans(x))
## 1 2 3 4 5 6
## 2.550 2.375 2.350 2.350 2.550 2.850
実際の場合では、このような使い方になるかと:
x$rmean <- rowMeans(x)
head(x)
## Sepal.Length Sepal.Width Petal.Length Petal.Width rmean
## 1 5.1 3.5 1.4 0.2 2.550
## 2 4.9 3.0 1.4 0.2 2.375
## 3 4.7 3.2 1.3 0.2 2.350
## 4 4.6 3.1 1.5 0.2 2.350
## 5 5.0 3.6 1.4 0.2 2.550
## 6 5.4 3.9 1.7 0.4 2.850
なお、rowSums()
もrowMeans()
も文字列など計算できない変数が含まれているとエラーを出しますので注意してください。また、na.rm=
オプションが使えますので、必要に応じて使ってください。
2つのデータフレームを準備します:
x <- data.frame(a=1:3,b=c("A","B","C"),c=11:13)
x
## a b c
## 1 1 A 11
## 2 2 B 12
## 3 3 C 13
y <- data.frame(a=2:4,b=c("B","C","D"),d=12:14)
y
## a b d
## 1 2 B 12
## 2 3 C 13
## 3 4 D 14
以降、これを使って説明します。
データフレームを結合するには、merge()
関数を使用します:
merge(x,y)
## a b c d
## 1 2 B 12 12
## 2 3 C 13 13
この場合、x
とy
で共通する変数(この場合a
とb
)をキー変数として、その2つが一致する行のみ取り出して結合させます。片方しかない列は、それぞれ残ることとなります。
データを落とすことなく結合させるには、all=TRUE
という引数を与えます:
merge(x,y,all=TRUE)
## a b c d
## 1 1 A 11 NA
## 2 2 B 12 12
## 3 3 C 13 13
## 4 4 D NA 14
この場合、2つのデータフレームで共通する列をキー変数として結合し、キー変数が一致しないレコード(行)は追加されます。なお値がない部分についてはNA
が入ります。
データフレームに行を追加する場合、rbind()
関数を使用します:
データフレームに列を追加する場合、cbind()
関数を使用します: