<< トップページへ

<< 目次へ

最終更新日 : 2015.4.29

dplyrによるデータフレーム操作



dplyrというデータフレームの操作に特化した便利なパッケージがあります。ただし、古典的な「書き方」を知っている人は無理に覚える必要はないかもしれません。試したことはありませんが、dplyrに含まれる関数を用いた方が高速に処理ができるそうです。

ここでは練習のために、Rに最初から入っているデータ:CO2を例にとって説明していきたいと思います。特に何もせずとも、Rのコンソール画面に CO2 と入力してみてください。そうすると以下のようなデータが表示されるはずです。

> CO2
   Plant        Type  Treatment conc uptake
1    Qn1      Quebec nonchilled   95   16.0
2    Qn1      Quebec nonchilled  175   30.4
3    Qn1      Quebec nonchilled  250   34.8
4    Qn1      Quebec nonchilled  350   37.2
5    Qn1      Quebec nonchilled  500   35.3
6    Qn1      Quebec nonchilled  675   39.2
7    Qn1      Quebec nonchilled 1000   39.7
8    Qn2      Quebec nonchilled   95   13.6
9    Qn2      Quebec nonchilled  175   27.3
10   Qn2      Quebec nonchilled  250   37.1
11   Qn2      Quebec nonchilled  350   41.8
12   Qn2      Quebec nonchilled  500   40.6
13   Qn2      Quebec nonchilled  675   41.4
14   Qn2      Quebec nonchilled 1000   44.3
15   Qn3      Quebec nonchilled   95   16.2
16   Qn3      Quebec nonchilled  175   32.4
(以下省略)


CO2には「Plant」、「Type」、「Treatment」、「conc」、「uptake」といった5つの変数が含まれています。


さて、まずはdplyrパッケージをインストールし、パッケージを読み込む必要があります。

> install.packages("dplyr")
> library(dplyr)



■行と列の抽出操作

古典的な書き方では [ ] を使うことで特定の条件にマッチするレコードを抽出することができました。これを filter() という関数を用いることで同じ操作ができます。古典的な書き方ではOR条件を | で示し、AND条件を & で示します。一方でfilter()ではOR条件を | で示し、AND条件を , で示します。

> CO2[CO2$Plant=="Qc1" & CO2$Type=="Quebec", ]   # 古典的な書き方 AND条件は & で示す
   Plant   Type Treatment conc uptake
22   Qc1 Quebec   chilled   95   14.2
23   Qc1 Quebec   chilled  175   24.1
24   Qc1 Quebec   chilled  250   30.3
25   Qc1 Quebec   chilled  350   34.6
26   Qc1 Quebec   chilled  500   32.5
27   Qc1 Quebec   chilled  675   35.4
28   Qc1 Quebec   chilled 1000   38.7

> filter(CO2, Plant=="Qc1", Type=="Quebec")      # filter()を用いる方法 AND条件は , で示す
  Plant   Type Treatment conc uptake
1   Qc1 Quebec   chilled   95   14.2
2   Qc1 Quebec   chilled  175   24.1
3   Qc1 Quebec   chilled  250   30.3
4   Qc1 Quebec   chilled  350   34.6
5   Qc1 Quebec   chilled  500   32.5
6   Qc1 Quebec   chilled  675   35.4
7   Qc1 Quebec   chilled 1000   38.7


さて古典的な書き方では、列の操作も行操作と同様に [ ] を使って必要な列を抽出することができました。これを select() という関数を使うことで実現できます。なお、必要な列を抽出するのとは逆に、不要な列を削除する(結果としてどちらも同じだが)場合は - を使うことで実現できます。例えば CO2[, -c(2,5)] もしくは select(CO2, -(2:5)) のように。

> CO2[, c(2,5)]                  # 古典的方法 列番号を指定Ver.
          Type uptake
1       Quebec   16.0
2       Quebec   30.4
3       Quebec   34.8
4       Quebec   37.2
5       Quebec   35.3

> CO2[, c("Type", "uptake")]     # 古典的方法 変数名を指定Ver.
          Type uptake
1       Quebec   16.0
2       Quebec   30.4
3       Quebec   34.8
4       Quebec   37.2
5       Quebec   35.3


> select(CO2, 2,5)               # select() 列番号を指定Ver.
          Type uptake
1       Quebec   16.0
2       Quebec   30.4
3       Quebec   34.8
4       Quebec   37.2
5       Quebec   35.3

> select(CO2, Type, uptake)      # select() 変数名を指定Ver.
          Type uptake
1       Quebec   16.0
2       Quebec   30.4
3       Quebec   34.8
4       Quebec   37.2
5       Quebec   35.3


列の操作でselect()を使った方が便利な例として、以下のような使い方があげられます。

> select(CO2, Plant:Treatment)     # 連続した変数を抽出する
   Plant        Type  Treatment
1    Qn1      Quebec nonchilled
2    Qn1      Quebec nonchilled
3    Qn1      Quebec nonchilled
4    Qn1      Quebec nonchilled
5    Qn1      Quebec nonchilled


元々のデータフレームに新たな変数を追加する場合、以前は cbind() を使うのが常套手段でしたが、 mutate() という関数を使うことで同様のことができます。

> mutate(CO2, new=uptake/100)     # CO2に対して、新たな変数newを列結合する
   Plant        Type  Treatment conc uptake   new
1    Qn1      Quebec nonchilled   95   16.0 0.160
2    Qn1      Quebec nonchilled  175   30.4 0.304
3    Qn1      Quebec nonchilled  250   34.8 0.348
4    Qn1      Quebec nonchilled  350   37.2 0.372
5    Qn1      Quebec nonchilled  500   35.3 0.353
  



■データフレームのソート(データフレームの並び替え)

従来、データフレームについてソートを行う場合、 order() を用いていました。しかし arrange() を使うことで簡単にソートができるようになっています。

> srt.indx <- order(CO2$uptake)               # 従来はorder()を用いてソートしていた
> CO2[srt.indx, ]                             # uptakeについて昇順ソート
   Plant        Type  Treatment conc uptake
71   Mc2 Mississippi    chilled   95    7.7
29   Qc2      Quebec    chilled   95    9.3
64   Mc1 Mississippi    chilled   95   10.5
43   Mn1 Mississippi nonchilled   95   10.6
78   Mc3 Mississippi    chilled   95   10.6
57   Mn3 Mississippi nonchilled   95   11.3

> arrange(CO2, uptake)                        # arrange()を使う場合
   Plant        Type  Treatment conc uptake
1    Mc2 Mississippi    chilled   95    7.7
2    Qc2      Quebec    chilled   95    9.3
3    Mc1 Mississippi    chilled   95   10.5
4    Mn1 Mississippi nonchilled   95   10.6
5    Mc3 Mississippi    chilled   95   10.6
6    Mn3 Mississippi nonchilled   95   11.3


どちらもデフォルトでは「昇順」ソートですが、「降順」ソートにすることもできます。また、複数の変数をキーとしてソートすることもできます。

## 従来どおりorder()を使う場合
#   2つの変数をキーに指定すると、どちらも降順になってしまうのが面倒
> srt.indx <- order(CO2$Treatment, CO2$uptake, decreasing=TRUE)
> CO2[srt.indx, ]
   Plant        Type  Treatment conc uptake
35   Qc2      Quebec    chilled 1000   42.4
42   Qc3      Quebec    chilled 1000   41.4
41   Qc3      Quebec    chilled  675   39.6
40   Qc3      Quebec    chilled  500   38.9
32   Qc2      Quebec    chilled  350   38.8
28   Qc1      Quebec    chilled 1000   38.7
33   Qc2      Quebec    chilled  500   38.6


## arrange()を使う場合
#   2つの変数を指定したとき、どちらか任意の方に「だけ」降順指定ができる(便利!)
> arrange(CO2, Treatment, desc(uptake))
   Plant        Type  Treatment conc uptake
1    Qn3      Quebec nonchilled 1000   45.5
2    Qn2      Quebec nonchilled 1000   44.3
3    Qn3      Quebec nonchilled  675   43.9
4    Qn3      Quebec nonchilled  500   42.9
5    Qn3      Quebec nonchilled  350   42.1
6    Qn2      Quebec nonchilled  350   41.8
7    Qn2      Quebec nonchilled  675   41.4



■グループ集計

通常、Rでグループ集計を行う際には tapply() を使うのが一般的でした。しかし、dplyrパッケージには group_by という関数と summarize() という関数が含まれており、これらを使うことでグループ集計ができます。

## Typeについて、uptakeの平均を計算する
> tapply(CO2$uptake, CO2$Type, mean)
     Quebec Mississippi 
   33.54286    20.88333


## 上記と同じことをgroup_byとsummarizeで実行してみる
> gCO2 <- group_by(CO2, Type)             # グループ化したい変数を指定し、新たなデータフレームを作成
> gCO2                                    # 中身を確認。Typeがグループ変数になっていることが確認できる
Source: local data frame [84 x 5]
Groups: Type

   Plant   Type  Treatment conc uptake
1    Qn1 Quebec nonchilled   95   16.0
2    Qn1 Quebec nonchilled  175   30.4
3    Qn1 Quebec nonchilled  250   34.8
4    Qn1 Quebec nonchilled  350   37.2
5    Qn1 Quebec nonchilled  500   35.3
6    Qn1 Quebec nonchilled  675   39.2
7    Qn1 Quebec nonchilled 1000   39.7
8    Qn2 Quebec nonchilled   95   13.6
9    Qn2 Quebec nonchilled  175   27.3
10   Qn2 Quebec nonchilled  250   37.1
..   ...    ...        ...  ...    ...

> summarize(gCO2, upt.M=mean(uptake))    # tapplyに該当する操作部分
Source: local data frame [2 x 2]

         Type    upt.M
1      Quebec 33.54286
2 Mississippi 20.88333

> summarize(gCO2, upt.M=n())             # ちなみに「カウント」したい場合はこのように書く
Source: local data frame [2 x 2]

         Type upt.M
1      Quebec    42
2 Mississippi    42


## グループ集計のキーとする変数は複数指定できる
> gCO2 <- group_by(CO2, Plant, Type, Treatment)
> gCO2
Source: local data frame [84 x 5]
Groups: Plant, Type, Treatment

   Plant   Type  Treatment conc uptake
1    Qn1 Quebec nonchilled   95   16.0
2    Qn1 Quebec nonchilled  175   30.4
3    Qn1 Quebec nonchilled  250   34.8
4    Qn1 Quebec nonchilled  350   37.2
5    Qn1 Quebec nonchilled  500   35.3
6    Qn1 Quebec nonchilled  675   39.2
7    Qn1 Quebec nonchilled 1000   39.7
8    Qn2 Quebec nonchilled   95   13.6
9    Qn2 Quebec nonchilled  175   27.3
10   Qn2 Quebec nonchilled  250   37.1
..   ...    ...        ...  ...    ...

> summarize(gCO2, Plant.count=mean(uptake))
Source: local data frame [12 x 4]
Groups: Plant, Type

   Plant        Type  Treatment Plant.count
1    Qn1      Quebec nonchilled    33.22857
2    Qn2      Quebec nonchilled    35.15714
3    Qn3      Quebec nonchilled    37.61429
4    Qc1      Quebec    chilled    29.97143
5    Qc3      Quebec    chilled    32.58571
6    Qc2      Quebec    chilled    32.70000
7    Mn3 Mississippi nonchilled    24.11429
8    Mn2 Mississippi nonchilled    27.34286
9    Mn1 Mississippi nonchilled    26.40000
10   Mc2 Mississippi    chilled    12.14286
11   Mc3 Mississippi    chilled    17.30000
12   Mc1 Mississippi    chilled    18.00000