4

data.table内部を使用するパッケージに取り組んでいます。このパッケージには、 by グループcount_by内の特定の変数の個別の ID の数を計算する関数があります。data.tableいくつかの助けを借りて ( R data.table: 関数で「可能なすべて」を渡す方法は? ) これを期待どおりに動作させることができました:

library(data.table)
#> Warning: package 'data.table' was built under R version 3.6.2

# create example data
sample_dt <- data.table(
    id = sort(rep(LETTERS[1:3], 3)),
    year = rep(2018L:2020L),
    x = runif(9)
)
sample_dt[id == "B" & year < 2020, x := NA_real_]

# define inner function
count_by <- function(DT, id_var, val_var, by = NULL) {
    id_var <- as.character(substitute(id_var))
    val_var <- as.character(substitute(val_var))

    eval(substitute(
        DT[!is.na(get(val_var)), .(distinct_ids = uniqueN(get(id_var))), by = by]
    ))
}

# test inner function -> works as expected
(reference <- count_by(sample_dt, id_var = id, val_var = x, by = year))
#>    year distinct_ids
#> 1: 2018            2
#> 2: 2019            2
#> 3: 2020            3

identical(count_by(sample_dt, "id", x, year)       , reference)
#> [1] TRUE
identical(count_by(sample_dt, "id", "x", year)     , reference)
#> [1] TRUE
identical(count_by(sample_dt, "id", x, "year")     , reference)
#> [1] TRUE
identical(count_by(sample_dt, "id", x, c("year"))  , reference)
#> [1] TRUE
identical(count_by(sample_dt, "id", "x", "year")   , reference)
#> [1] TRUE
identical(count_by(sample_dt, "id", "x", c("year")), reference)
#> [1] TRUE
identical(count_by(sample_dt, id, "x", year)       , reference)
#> [1] TRUE
identical(count_by(sample_dt, id, "x", "year")     , reference)
#> [1] TRUE
identical(count_by(sample_dt, id, "x", c("year"))  , reference)
#> [1] TRUE
identical(count_by(sample_dt, id, x, "year")       , reference)
#> [1] TRUE
identical(count_by(sample_dt, id, x, c("year"))    , reference)
#> [1] TRUE

reprex パッケージ(v0.3.0)により 2020-02-20 に作成

ここで、関数を別の関数内で使用したいと思いcount_by()ます (以下の最小限の例):

# define wrapper function
wrapper <- function(data, id_var, val_var, by = NULL) {
    data <- as.data.table(data)
    count_by(data, id_var, val_var, by)
}

# test wrapper function
wrapper(sample_dt, id_var = id, val_var = x, by = year)
#> Error in .(distinct_ids = uniqueN(get("id_var"))): could not find function "."

reprex パッケージ(v0.3.0)により 2020-02-20 に作成

デバッグすると、が from から呼び出されcount_by()た場合、も次のように置換されることがわかります。count_by()wrapper()substitute(DT[...])DTdata

Browse[2]> substitute(
+         DT[!is.na(get(val_var)), .(distinct_ids = uniqueN(get(id_var))), by = by]
+     )
data[!is.na(get("val_var")), .(distinct_ids = uniqueN(get("id_var"))), 
    by = by]

data関数環境では使用できないため、count_by()評価されutils::dataてエラーが発生します。これで問題は明確になりますが、解決策が思いつきません。

が適切に機能DT[...]するためには、式全体を置き換える必要があります ( R data.table: How to pass "everything possible" to by in a function?またはpass variables and names to data.table function を参照)。しかし、代用されないために表現全体を代用することはできません。byDT

このジレンマの解決策は何ですか?

4

2 に答える 2