R Language
データ表
サーチ…
前書き
Data.tableは、基盤Rからのデータフレームの機能を拡張し、特にパフォーマンスと構文を向上させるパッケージです。詳細については、パッケージのドキュメント領域( data.table入門)を参照してください。
構文
-
DT[i, j, by]
#DT [where | select | update | do、by] -
DT[...][...]
#連鎖 -
################# Shortcuts, special functions and special symbols inside DT[...]
- 。()
list()の代わりにいくつかの引数に# - J()
リスト内の#がiの#で置き換えられました。 - :=
#in j、列の追加または変更に使用される関数 - N
#iで、行の総数
#in j、グループ内の行数 - 。私
#in j、テーブル内の行番号のベクトル(iでフィルタリングされた) - 。SD
#in j、データの現在のサブセット
.SDcols引数で選択された# - .GRP
#in j、データのサブセットの現在のインデックス - 。によって
#in j、データの現在のサブセットの値によるリスト - V1、V2、...
#jで作成された名前のない列のデフォルト名 -
################# Joins inside DT[...]
- DT1 [DT2、on、j]
#2つのテーブルを結合する - 私。*
#結合後のDT2の列の特別な接頭辞 - by = EACHI
#特殊オプションは結合でのみ使用可能です - DT1 [!DT2、on、j]
#2つのテーブルのアンチ・ジョイン - DT1 [DT2、on、roll、j]
#2つのテーブルを結合し、最後の列をon = -
################# Reshaping, stacking and splitting
- 溶融(DT、id.vars、measure.vars)
#長い形式に変換する
#複数の列の場合は、measure.vars = patterns(...)を使用します。 - dcast(DT、数式)
#ワイドフォーマットに変換する - rbind(DT1、DT2、...)
#stack列挙されたdata.tables - rbindlist(DT_list、idcol)
#データテーブルのリストをスタックする - 分割(DT、by)
#data.tableをリストに分割する -
################# Some other functions specialized for data.tables
- ホバリング
#重複結合 - マージ
#2つのテーブルを結合する別の方法 - セット
#列を追加または変更する別の方法 - fintersect、fsetdiff、funion、fsetequal、ユニーク、重複、anyDuplicated
#行を要素とするset-theory操作 - ユニークN
#異なる行の数 - rowidv(DT、cols)
#colsで指定された各グループ内の行ID(1〜N) - rleidv(DT、cols)
#colsの実行によって決定される各グループ内のグループID(1〜.GRP) - シフト(DT、n、タイプ= c(「ラグ」、「リード」))
#すべての列にシフト演算子を適用する - setorder、setcolorder、setnames、setkey、setindex、setattr
#属性と参照順の変更
備考
インストールとサポート
data.tableパッケージをインストールするには:
# install from CRAN
install.packages("data.table")
# or install development version
install.packages("data.table", type = "source", repos = "http://Rdatatable.github.io/data.table")
# and to revert from devel to CRAN, the current version must first be removed
remove.packages("data.table")
install.packages("data.table")
パッケージの公式サイトには、ヘルプの開始を支援するwikiページ、およびウェブ上のプレゼンテーションと記事のリストがあります。 StackOverflowや他の場所で質問をする前に、サポートページをお読みください 。
パッケージのロード
上記の例の関数の多くは、data.table名前空間に存在します。それらを使用するには、 library(data.table)
ような行を最初に追加するか、単純にfread
代わりにdata.table::fread
ようなフルパスを使用する必要があります。個々の関数のヘルプについては、構文はhelp("fread")
または?fread
です。パッケージがロードされていない場合は、 ?data.table::fread
ようなフルネームを使用してください。
data.tableの作成
data.tableは、基底Rからのdata.frameクラスの拡張バージョンです。したがって、 class()
属性はvector "data.table" "data.frame"
あり、data.frameで機能する関数もdata.tableで作業します。 data.tableを作成、ロード、または強制する方法はたくさんあります。
ビルド
data.table
パッケージをインストールしてアクティブ化することを忘れないでください
library(data.table)
同じ名前のコンストラクタがあります:
DT <- data.table(
x = letters[1:5],
y = 1:5,
z = (1:5) > 3
)
# x y z
# 1: a 1 FALSE
# 2: b 2 FALSE
# 3: c 3 FALSE
# 4: d 4 TRUE
# 5: e 5 TRUE
data.frame
とは異なり、 data.table
は文字列をファクタに強制しません。
sapply(DT, class)
# x y z
# "character" "integer" "logical"
読む
テキストファイルから読み込むことができます:
dt <- fread("my_file.csv")
read.csv
とは異なり、 fread
は文字列を要素ではなく文字列として読み込みます。
data.frameを変更する
効率を上げるため、data.tableはdata.frameまたはlistを変更して、(コピーを作成せずに、またはメモリの場所を変更せずに)data.tableをその場で作成する方法を提供します:
# example data.frame
DF <- data.frame(x = letters[1:5], y = 1:5, z = (1:5) > 3)
# modification
setDT(DF)
オブジェクトDF
はインプレースで修正されているため、結果を<-
割り当てないことに注意してください。 data.frameのクラス属性は保持されます:
sapply(DF, class)
# x y z
# "factor" "integer" "logical"
オブジェクトをdata.tableに強制する
あなたが持っている場合はlist
、 data.frame
、またはdata.table
、あなたが使用する必要がありますsetDT
に変換する機能を data.table
それはコピーを(これは作るのではなく、参照することにより、変換を行いますので、 as.data.table
ありません)。大規模なデータセットを扱う場合は、これが重要です。
あなたは(このようなマトリックスのような)他のRオブジェクトを持っている場合は、使用する必要がありますas.data.table
にそれを強制するdata.table
。
mat <- matrix(0, ncol = 10, nrow = 10)
DT <- as.data.table(mat)
# or
DT <- data.table(mat)
列の追加と変更
DT[where, select|update|do, by]
構文は、data.tableの列を処理するために使用されます。
- "where"部分が
i
引数です。 - "select | update | do"部分は
j
引数です
これらの2つの引数は、通常、名前ではなく位置によって渡されます。
以下の例のデータは
mtcars = data.table(mtcars, keep.rownames = TRUE)
列全体の編集
新しい列を割り当てるには、 j
内で:=
演算子を使用します。
mtcars[, mpg_sq := mpg^2]
NULL
設定して列を削除する:
mtcars[, mpg_sq := NULL]
:=
演算子の多変量形式を使用して複数の列を追加する:
mtcars[, `:=`(mpg_sq = mpg^2, wt_sqrt = sqrt(wt))]
# or
mtcars[, c("mpg_sq", "wt_sqrt") := .(mpg^2, sqrt(wt))]
列が依存しており、順番に定義する必要がある場合は、1つの方法があります。
mtcars[, c("mpg_sq", "mpg2_hp") := .(temp1 <- mpg^2, temp1/hp)]
.()
構文は、 LHS := RHS
の右側が列のリストである場合に使用されます。
動的に決定される列名の場合は、かっこを使用します。
vn = "mpg_sq"
mtcars[, (vn) := mpg^2]
ほとんどの場合、カラムはset
で変更することもできます。
set(mtcars, j = "hp_over_wt", v = mtcars$hp/mtcars$wt)
列のサブセットの編集
i
引数を使用して、行の部分集合を「編集」する場所を指定します。
mtcars[1:3, newvar := "Hello"]
# or
set(mtcars, j = "newvar", i = 1:3, v = "Hello")
data.frameの場合と同様に、行番号または論理テストを使用してサブセット化することができます。 i
で「結合」を使用することもできますが、別の例ではより複雑な作業が含まれています。
列属性の編集
levels<-
またはnames<-
などの属性を編集する関数は、実際にオブジェクトを変更されたコピーで置き換えます。 data.tableの1つの列でのみ使用されても、オブジェクト全体がコピーされて置き換えられます。
コピーを持たないオブジェクトを変更するには、 setnames
を使用してdata.tableまたはdata.frameおよびsetattr
の列名を変更し、オブジェクトの属性を変更します。
# Print a message to the console whenever the data.table is copied
tracemem(mtcars)
mtcars[, cyl2 := factor(cyl)]
# Neither of these statements copy the data.table
setnames(mtcars, old = "cyl2", new = "cyl_fac")
setattr(mtcars$cyl_fac, "levels", c("four", "six", "eight"))
# Each of these statements copies the data.table
names(mtcars)[names(mtcars) == "cyl_fac"] <- "cf"
levels(mtcars$cf) <- c("IV", "VI", "VIII")
これらの変更は参照によって行われるため、 グローバルに変更されています。ある環境でそれらを変更すると、すべての環境のオブジェクトに影響します。
# This function also changes the levels in the global environment
edit_levels <- function(x) setattr(x, "levels", c("low", "med", "high"))
edit_levels(mtcars$cyl_factor)
data.tableの特殊記号
。SD
.SD
は、 data.table
で使用さby
すべての列を除いて、各グループのdata.table
のサブセットを参照します。
.SD
とlapply
は、 data.table
グループdata.table
に複数のカラムに任意の関数を適用するために使用できます
同じ組み込みデータセットmtcars
を引き続き使用しmtcars
。
mtcars = data.table(mtcars) # Let's not include rownames to keep things simpler
データセット内のすべての列の、 シリンダ数 、 cyl
平均:
mtcars[ , lapply(.SD, mean), by = cyl]
# cyl mpg disp hp drat wt qsec vs am gear carb
#1: 6 19.74286 183.3143 122.28571 3.585714 3.117143 17.97714 0.5714286 0.4285714 3.857143 3.428571
#2: 4 26.66364 105.1364 82.63636 4.070909 2.285727 19.13727 0.9090909 0.7272727 4.090909 1.545455
#3: 8 15.10000 353.1000 209.21429 3.229286 3.999214 16.77214 0.0000000 0.1428571 3.285714 3.500000
cyl
とは別に、 vs
、 am
、 gear
、 carb
などのデータセットには他のカテゴリの列があります。これらの列のmean
を取ることは実際には意味がありません。だから、これらの列を除外しましょう。これは、 .SDcols
が絵になる場所です。
.SDcols
.SDcols
の列を指定data.table
に含まれています.SD
。
歯車の数で、データセットのすべての列(連続列)の平均gear
、及び気筒数 、 cyl
によって配置、 gear
とcyl
:
# All the continuous variables in the dataset
cols_chosen <- c("mpg", "disp", "hp", "drat", "wt", "qsec")
mtcars[order(gear, cyl), lapply(.SD, mean), by = .(gear, cyl), .SDcols = cols_chosen]
# gear cyl mpg disp hp drat wt qsec
#1: 3 4 21.500 120.1000 97.0000 3.700000 2.465000 20.0100
#2: 3 6 19.750 241.5000 107.5000 2.920000 3.337500 19.8300
#3: 3 8 15.050 357.6167 194.1667 3.120833 4.104083 17.1425
#4: 4 4 26.925 102.6250 76.0000 4.110000 2.378125 19.6125
#5: 4 6 19.750 163.8000 116.5000 3.910000 3.093750 17.6700
#6: 5 4 28.200 107.7000 102.0000 4.100000 1.826500 16.8000
#7: 5 6 19.700 145.0000 175.0000 3.620000 2.770000 15.5000
#8: 5 8 15.400 326.0000 299.5000 3.880000 3.370000 14.5500
たぶん、グループ別にmean
を計算したくないかもしれません。データセット内のすべての車の平均を計算するために、 by
変数は指定しません。
mtcars[ , lapply(.SD, mean), .SDcols = cols_chosen]
# mpg disp hp drat wt qsec
#1: 20.09062 230.7219 146.6875 3.596563 3.21725 17.84875
注意:
- あらかじめ
cols_chosen
を定義する必要はありません。.SDcols
は列名を直接取ることができます -
.SDcols
は列番号のベクトルを直接取ることもできます。上記の例では、これはmtcars[ , lapply(.SD, mean), .SDcols = c(1,3:7)]
N
.N
はグループ内の行数の省略形です。
iris[, .(count=.N), by=Species]
# Species count
#1: setosa 50
#2: versicolor 50
#3: virginica 50
data.frameとdata.tableの両方と互換性のあるコードを書く
サブセット設定構文の違い
data.table
は、 data.frame
、 matrix
、(2D) array
他に、Rで利用可能ないくつかの2次元データ構造の1つです。これらのクラスはすべてサブセット化に非常によく似た構文を使用しますが、 A[rows, cols]
スキーマです。
保存されている次のデータを検討matrix
、 data.frame
とdata.table
:
ma <- matrix(rnorm(12), nrow=4, dimnames=list(letters[1:4], c('X', 'Y', 'Z')))
df <- as.data.frame(ma)
dt <- as.data.table(ma)
ma[2:3] #---> returns the 2nd and 3rd items, as if 'ma' were a vector (because it is!)
df[2:3] #---> returns the 2nd and 3rd columns
dt[2:3] #---> returns the 2nd and 3rd rows!
何が返されるかを確認したい場合は、 明示的にする方が良いです。
特定の行を取得するには、範囲の後にカンマを追加します。
ma[2:3, ] # \
df[2:3, ] # }---> returns the 2nd and 3rd rows
dt[2:3, ] # /
しかし、 列をサブセット化したい場合、いくつかのケースは異なって解釈されます。変数に格納されていない整数または文字インデックスを使用して、3つのすべてを同じ方法でサブセット化することができます。
ma[, 2:3] # \
df[, 2:3] # \
dt[, 2:3] # }---> returns the 2nd and 3rd columns
ma[, c("Y", "Z")] # /
df[, c("Y", "Z")] # /
dt[, c("Y", "Z")] # /
ただし、引用符で囲まれていない変数名では異なります
mycols <- 2:3
ma[, mycols] # \
df[, mycols] # }---> returns the 2nd and 3rd columns
dt[, mycols, with = FALSE] # /
dt[, mycols] # ---> Raises an error
最後のケースでは、 mycols
は列の名前として評価されます。 dt
はmycols
という名前の列を見つけることができないため、エラーが発生します。
注: data.table
パッケージdata.table
バージョンでは、この動作は若干異なります。 dt
を環境として使用して列索引内のものは評価されていました。だから、 dt[, 2:3]
とdt[, mycols]
はベクトル2:3
返します。変数mycols
が親環境に存在するため、2番目のケースではエラーは発生しません。
data.frameとdata.tableとの互換性を維持するための戦略
data.frame
とdata.table
動作することが保証されているコードを書く理由はたくさんあります。おそらく、 data.frame
使用を余儀なくされたり、使用方法がわからないコードを共有する必要があるかもしれません。したがって、これを達成するためのいくつかの主要な戦略が利便性の順にあります:
- 両方のクラスで同じように動作する構文を使用します。
- 最短の構文と同じことをする共通の関数を使用してください。
-
data.table
をdata.table
として動作させdata.frame
(例:特定のメソッドprint.data.frame
呼び出します)。 - それらを最終的には
list
として扱います。 - 何かをする前にテーブルを
data.frame
に変換します(巨大なテーブルの場合は悪い考えです)。 - 依存関係が問題でない場合は、表を
data.table
変換します。
サブセット行その単純な、 [, ]
セレクタをカンマでつけてください:
A[1:10, ]
A[A$var > 17, ] # A[var > 17, ] just works for data.table
サブセット列。単一の列が必要な場合は、 $
または[[ ]]
セレクタを使用します。
A$var
colname <- 'var'
A[[colname]]
A[[1]]
均一な方法で複数の列を取得したい場合は、少しアピールする必要があります。
B <- `[.data.frame`(A, 2:4)
# We can give it a better name
select <- `[.data.frame`
B <- select(A, 2:4)
C <- select(A, c('foo', 'bar'))
サブセット「索引付け」行 data.frame
はdata.frame
がありrow.names
、 data.table
は独自のkey
機能があります。最善の方法は、 row.names
完全に避け、 row.names
の場合は既存の最適化をdata.table
することです。
B <- A[A$var != 0, ]
# or...
B <- with(A, A[var != 0, ]) # data.table will silently index A by var before subsetting
stuff <- c('a', 'c', 'f')
C <- A[match(stuff, A$name), ] # really worse than: setkey(A); A[stuff, ]
1列のテーブルを取得し、ベクトルとして行を取得します。これまでの私たちが見たことは簡単です:
B <- select(A, 2) #---> a table with just the second column
C <- unlist(A[1, ]) #---> the first row as a vector (coerced if necessary)
data.tableにキーを設定する
はい、あなたは1.9.6前にSETKEYする必要があります
過去には(1.9.6より前)、テーブルのキーとしてカラムを設定することで、特に大きなテーブルの場合、 data.table
が高速化されました。 [検索速度が544倍向上した2015年9月版のイントロ・ビネット・ページ5を参照]テーブルを設定するときに、この設定キーを 'setkey'で使用するか、 'key ='列を設定する古いコードがあります。
library(data.table)
DT <- data.table(
x = letters[1:5],
y = 5:1,
z = (1:5) > 3
)
#> DT
# x y z
#1: a 5 FALSE
#2: b 4 FALSE
#3: c 3 FALSE
#4: d 2 TRUE
#5: e 1 TRUE
setkey
コマンドでキーを設定します。複数の列を持つキーを持つことができます。
setkey(DT, y)
テーブルのテーブルのキーを確認する()
tables()
> tables()
NAME NROW NCOL MB COLS KEY
[1,] DT 5 3 1 x,y,z y
Total: 1MB
これはあなたのデータを再ソートすることに注意してください。
#> DT
# x y z
#1: e 1 TRUE
#2: d 2 TRUE
#3: c 3 FALSE
#4: b 4 FALSE
#5: a 5 FALSE
今は不要です
v1.9.6以前は、特にテーブルを結合する特定の操作のキーを設定する必要がありました。 data.tableの開発者はスピードアップし、キーの依存関係を置き換えることができる"on="
機能を導入しました。詳細な議論については、ここのSOの回答を参照してください。
2017年1月、開発者は二次インデックスの周囲にバイナリを書き込んで、 "on"構文を説明し、高速インデックス作成のために他の列を識別できるようにしました。
セカンダリインデックスを作成しますか?
keyと似た方法で、あなたはsetindex(DT, key.col)
またはsetindex(DT, key.col)
setindexv(DT, "key.col.string")
設定できます。ここでDTはあなたのdata.tableです。 setindex(DT, NULL)
すべてのインデックスを削除しsetindex(DT, NULL)
。
indices(DT)
を使用してセカンダリインデックスを参照してください。
なぜ二次指標ですか?
これは 、(キーとは異なり)テーブルをソートしませんが、 "on"構文を使用して迅速なインデックス作成を可能にします。キーは1つだけですが、複数のセカンダリインデックスを使用することができます。これにより、テーブルのキーを再作成して解決する必要がなくなります。サブセット化する列を変更すると、サブセット化が高速化されます。
上の例ではyが表DTのキーであったことを思い出してください。
DT
# x y z
# 1: e 1 TRUE
# 2: d 2 TRUE
# 3: c 3 FALSE
# 4: b 4 FALSE
# 5: a 5 FALSE
# Let us set x as index
setindex(DT, x)
# Use indices to see what has been set
indices(DT)
# [1] "x"
# fast subset using index and not keyed column
DT["c", on ="x"]
#x y z
#1: c 3 FALSE
# old way would have been rekeying DT from y to x, doing subset and
# perhaps keying back to y (now we save two sorts)
# This is a toy example above but would have been more valuable with big data sets