98

data.table変数名が文字ベクトルに格納されている場合、どのように変数を参照しますか?たとえば、これは次の場合に機能しますdata.frame

df <- data.frame(col1 = 1:3)
colname <- "col1"
df[colname] <- 4:6
df
#   col1
# 1    4
# 2    5
# 3    6

表記の有無にかかわらず、data.tableに対してこれと同じ操作を実行するにはどうすればよい:=ですか?の明らかなことはdt[ , list(colname)]機能しません(私はそれを期待していませんでした)。

4

6 に答える 6

138

プログラムで変数を選択する2 つの方法:

  1. with = FALSE:

     DT = data.table(col1 = 1:3)
     colname = "col1"
     DT[, colname, with = FALSE] 
     #    col1
     # 1:    1
     # 2:    2
     # 3:    3
    
  2. 「ドット ドット」( ..) プレフィックス:

     DT[, ..colname]    
     #    col1
     # 1:    1
     # 2:    2
     # 3:    3
    

「ドット ドット」( ..) 表記の詳細については、1.10.2 の新機能を参照してください(現在、ヘルプ テキストには記載されていません)。

変数に代入:=するには、左辺を括弧で囲みます:

DT[, (colname) := 4:6]    
#    col1
# 1:    4
# 2:    5
# 3:    6

後者は、列ベクトル全体を参照で置き換えるため、列plonkとして知られています。サブセットiが存在する場合は、参照によってサブアサインされます。前後のかっこは、 (colname)2014 年 10 月の CRAN のバージョン v1.9.4 で導入された省略形です。ニュース アイテムは次のとおりです。

with = FALSEwith:=の LHS:=を括弧で囲むことがしばらくの間好まれてきたため、 with の使用はすべての場合で推奨されなくなりました。

colVar = "col1"
DT[, (colVar) := 1]                             # please change to this
DT[, c("col1", "col2") := 1]                    # no change
DT[, 2:4 := 1]                                  # no change
DT[, c("col1","col2") := list(sum(a), mean(b))]  # no change
DT[, `:=`(...), by = ...]                       # no change

の詳細セクションも参照して?`:=`ください。

DT[i, (colnamevector) := value]
# [...] The parens are enough to stop the LHS being a symbol

そして、コメントでさらに質問に答えるために、ここに1つの方法があります(いつものように多くの方法があります):

DT[, colname := cumsum(get(colname)), with = FALSE]
#    col1
# 1:    4
# 2:    9
# 3:   15 

または、サーバーに送信する動的 SQL ステートメントを構築するevalのと同様に、に対してのみ読み取り、書き込み、およびデバッグする方が簡単であることがわかる場合があります。paste

expr = paste0("DT[,",colname,":=cumsum(",colname,")]")
expr
# [1] "DT[,col1:=cumsum(col1)]"

eval(parse(text=expr))
#    col1
# 1:    4
# 2:   13
# 3:   28

それを頻繁に行う場合は、ヘルパー関数を定義できますEVAL

EVAL = function(...)eval(parse(text=paste0(...)),envir=parent.frame(2))

EVAL("DT[,",colname,":=cumsum(",colname,")]")
#    col1
# 1:    4
# 2:   17
# 3:   45

1.8.2では効率がdata.table自動的に最適化されるため、この方法jを使用することをお勧めしますevalget()injは、たとえば、いくつかの最適化を防ぎます。

または、ありますset()。の低オーバーヘッドで機能的な形式で:=、ここでは問題ありません。を参照してください?set

set(DT, j = colname, value = cumsum(DT[[colname]]))
DT
#    col1
# 1:    4
# 2:   21
# 3:   66
于 2012-09-12T16:05:27.197 に答える