18

の小さな R の問題で立ち往生していdata.tableます。あなたの助けに感謝します。これを行うにはどうすればよいですか:

getResult <- function(dt, expr, gby) {
  e <- substitute(expr)
  b <- substitute(gby)
  return(dt[,eval(e),by=b])
}

v1 <- "Sepal.Length"
v2 <- "Species"

dt <- data.table(iris)
rDT <- getResult(dt, sum(v1, na.rm=TRUE), v2)

次のエラーが表示されます。

sum(v1, na.rm = TRUE) のエラー: 引数の無効な「タイプ」(文字)

現在、両方ともv1v2のプログラムから文字変数として渡されるため、これを行うことはできませんv1<- quote(Sepal.Length)

4

1 に答える 1

22

コメントでのフローデルの回答に代わるものは次のとおりです。

e <- parse(text = paste0("sum(", v1, ", na.rm = TRUE)"))

b <- parse(text = v2)

rDT2 <- dt[, eval(e), by = eval(b)]

#               b    V1
# [1,]     setosa 250.3
# [2,] versicolor 296.8
# [3,]  virginica 329.4

編集:

そして、これを関数に入れると、

getResult <- function(dt, expr, gby){
  return(dt[, eval(expr), by = eval(gby)])
}

(dtR <- getResult(dt = dt, expr = e, gby = b))
# gives the same result as above


マシューからの編集:paste0およびeval\quoteメソッドが場合によってはより高速になる 微妙な理由getもあります。グループ化が高速である理由の 1 つは、 が使用する列をdata.table調べjてから、使用された列のみをサブセット化することです (FAQ 1.12 および 3.1)。それを行うために使用base::all.vars(j)します。使用get()jの列で使用する場合は非表示にall.varsなり、式で必要なdata.table場合に備えてすべての列をサブセット化するようにフォールバックします (解決するためにが追加された でシンボルが使用されている場合と同様)。とにかくすべての列が使用されている場合、違いはありませんが、たとえば 1e7x100 の場合、グループ化されたj.SDj.SDcolsDTj=sum(V1)j=sum(get("V1"))そのため、グループ化よりもはるかに高速である必要があります。少なくとも、それが起こるはずであり、そうでない場合はバグである可能性があります。一方、多くのクエリが動的に構築され、繰り返されている場合は、それに時間がかかる可能性がpaste0ありparseます。すべては本当に依存します。設定により、 でverbose=TRUE使用されていると検出された列に関するメッセージが出力されj、確認できるようになります。

于 2012-05-20T18:44:12.637 に答える