4

ここで説明したのと同じことをしたい、つまり、欠落している行を data.table に追加したい。私が直面している唯一の追加の問題は、キー列、つまり自己結合に使用される行の数を柔軟にしたいということです。

上記のリンクで行われていることを基本的に繰り返す小さな例を次に示します。

df <- data.frame(fundID   = rep(letters[1:4], each=6),
                 cfType   = rep(c("D", "D", "T", "T", "R", "R"), times=4),
                 variable = rep(c(1,3), times=12),
                 value    = 1:24)
DT <- as.data.table(df)
idCols <- c("fundID", "cfType")
setkeyv(DT, c(idCols, "variable"))
DT[CJ(unique(df$fundID), unique(df$cfType), seq(from=min(variable), to=max(variable))), nomatch=NA]

気になるのは最後の行です。柔軟性を持たせたいので (たとえば、関数内で使用する場合)、手動でidCols入力したくありません。unique(df$fundID), unique(df$cfType)ただし、これに対する回避策は見つかりません。のサブセットを自動的dfにベクトルに分割しようとする試みはすべて、CJエラー メッセージError in setkeyv(x, cols, verbose = verbose) : Column 'V1' is type 'list' which is not (currently) allowedで失敗しますキー列タイプとして。

CJ(sapply(df[, idCols], unique))
CJ(unique(df[, idCols]))
CJ(as.vector(unique(df[, idCols])))
CJ(unique(DT[, idCols, with=FALSE]))

私も自分で式を構築しようとしました:

str <- ""
for (i in idCols) {
  str <- paste0(str, "unique(df$", i, "), ")
}
str <- paste0(str, "seq(from=min(variable), to=max(variable))")
str
[1] "unique(df$fundID), unique(df$cfType), seq(from=min(variable), to=max(variable))"

しかし、私は使い方がわかりませんstr。これはすべて失敗します:

CJ(eval(str))
CJ(substitute(str))
CJ(call(str))

誰か良い回避策を知っていますか?

4

2 に答える 2

4

マイケルの答えは素晴らしいです。do.call確かCJに、そのように柔軟に呼び出す必要があります。

式構築アプローチを明確にし、コードから開始しますが、パーツを削除します (の範囲内で評価されるdf$ため、リンクされた回答では不要であり、実行されません) :iDT

str <- "" 
for (i in idCols) { 
  str <- paste0(str, "unique(", i, "), ") 
} 
str <- paste0(str, "seq(from=min(variable), to=max(variable))") 
str 
[1] "unique(fundID), unique(cfType), seq(from=min(variable), to=max(variable))" 

それは次のとおりです。

expr <- parse(text=paste0("CJ(",str,")"))
DT[eval(expr),nomatch=NA]

または、代わりにクエリ全体を動的に構築して評価します。

eval(parse(text=paste0("DT[CJ(",str,"),nomatch=NA")))

そして、これが頻繁に行われる場合は、ヘルパー関数を自分で作成する価値があるかもしれません:

E = function(...) eval(parse(text=paste0(...)))

に減らすには:

E("DT[CJ(",str,"),nomatch=NA")
于 2012-08-08T15:11:19.300 に答える
3

私は data.table パッケージを使用したことがないので、ここでマークを見逃していたら許してください。ここでは多くのことが起こっています。を読むことから始めdo.callます。これにより、提供されたリストによって引数が指定される、一種の非伝統的な方法で任意の関数を評価できます (リスト内の各要素は、明示的に名前が付けられていない限り、関数の引数と位置的に一致します)。min(df$variable)の代わりに指定する必要があることにも注意してmin(variable)ください。スコーピングに関する Hadley のページを読んで、ここで問題を理解してください。

CJargs <- lapply(df[, idCols], unique)
names(CJargs) <- NULL
CJargs[[length(CJargs) +1]] <- seq(from=min(df$variable), to=max(df$variable))
DT[do.call("CJ", CJargs),nomatch=NA]
于 2012-07-26T22:18:12.910 に答える