data.tableの.I関連の話

irisデータにおいて、Species単位で最大のSepal.Lengthを返す行のデータを取得したい
twitter上でdata.tableマイスター達に教えていただいたので復習しておく。

.Iと組み合わせることでbyで指定したグループ単位の行番号が返ってくる

library("data.table")
DT <- as.data.table(iris)
DT[,.I[which.max(Sepal.Length)], by=Species]
#       Species  V1
# 1:     setosa  15
# 2: versicolor  51
# 3:  virginica 132

data.tableのi部分に行番号を指定することで取得大成功。

DT[DT[,.I[which.max(Sepal.Length)], by=Species]$V1]
#    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
# 1:          5.8         4.0          1.2         0.2     setosa
# 2:          7.0         3.2          4.7         1.4 versicolor
# 3:          7.9         3.8          6.4         2.0  virginica


身もふたもないけど、data.tableの文法に悩んですぐ解決しない場合はdplyr使うのが手っ取り早い。
こんな処理でいちいち考えたくない。

library("dplyr")
DT %>% group_by(Species) %>% filter(Sepal.Length==max(Sepal.Length))
# Source: local data table [3 x 5]
# Groups: Species
# 
#   Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
# 1          5.8         4.0          1.2         0.2     setosa
# 2          7.0         3.2          4.7         1.4 versicolor
# 3          7.9         3.8          6.4         2.0  virginica


.Iなどのspecial variableについてはdata.tableのパッケージヘルプ(?data.table)に書いてある。
.Iについての説明は以下の通り。

.I is an integer vector equal to seq_len(nrow(x)).
While grouping, it holds for each item in the group, it's row location in x.
This is useful to subset in j; e.g. DT[, .I[which.max(somecol)], by=grp].