質問
私は説明したのと同じことをしたい ここに, 、すなわち欠落している行をデータに追加します。テーブル。私が直面している唯一の追加の難しさは、キー列の数が必要なことです。自己結合に使用される行は、柔軟である必要があります。
上記のリンクで行われたことを基本的に繰り返す小さな例を次に示します:
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
, 、エラーメッセージで失敗する Setkeyv(x,cols,verbose=verbose)のエラー :列'V1'はタイプ'list'であり、キー列タイプとして(現在)許可されていません。
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))
誰かが良い回避策を知っていますか?
解決
私は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]
他のヒント
マイケルの答えは素晴らしいです。 do.call
実際に呼び出すために必要です CJ
そのように柔軟に、afaik。
式を構築するアプローチを明確にし、コードから始めますが、 df$
部品(リンクされた答えでは必要ではなく、行われていません。 i
の範囲内で評価されます DT
) :
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")