2016-09-11 5 views
1

関数fへの最初の呼び出しは機能し、2番目の呼び出しは機能しません。どのように私は文字列( "v")を関数fに渡して、関数がexspectedとして機能するようにすることができますか?変数を期待する関数に文字列をパラメータとして渡す方法

library(data.table) 

f<-function(t,x) t[,deparse(substitute(x)),with=F] 

dat<-data.table(v="a") 

f(dat,v) 
# v 
# 1: a 

f(dat,eval(parse(text="v"))) 
# Error in `[.data.table`(t, , deparse(substitute(x)), with = F) : 
# column(s) not found: eval(parse(text = "v")) 
+5

'dat [、.SDcols = cols]'のように 'dat [、mget(col)]'や '.SD'のように' .SDcols'を使って 'cols = "v" '。同じ関数の引数に(列の)*と*を文字ベクトルとして持たせることは、問題とあいまいさを招いています。 – Arun

答えて

3

それはもうワンライナーではありませんが、あなたはあなたが渡している何のためにテストすることができます。

library(data.table) 
library(purrr) 

dat <- data.table(v="a") 

f <- function(dt, x) { 

    # first, see if 'x' is a variable holding a string with a column name 

    seval <- safely(eval) 
    res <- seval(x, dt, parent.frame()) 

    # if it is, then get the value, otherwise substitute() it 

    if ((!is.null(res$result)) && inherits(res$result, "character")) { 
    y <- res$result 
    } else { 
    y <- substitute(x) 
    } 

    # if it's a bare name, then we deparse it, otherwise we turn 
    # the string into name and then deparse it 

    if (inherits(y, "name")) { 
    y <- deparse(y) 
    } else if (inherits(y, "character")) { 
    y <- deparse(as.name(x)) 
    } 

    dt[, y, with=FALSE] 

} 

f(dat,v) 
## v 
## 1: a 

f(dat, "v") 
## v 
## 1: a 

V <- "v" 
f(dat, V) 
## v 
## 1: a 

f(dat, VVV) 
#> throws an Error 

私が使用して好きではないので、私はdttからそれを切り替えます変数名として組み込み関数の名前(t()のようなもの)を私が実際に持っていなければ。より大きなコードブロックに微妙なエラーが導入され、デバッグに苛立つことがあります。

f()を実行するたびに、f()関数の外にsafely()呼び出しを呼び出して関数呼び出しを保存することもできます。あなたが好きなら、古い学校try()を代わりに使うことができますが、ある日は壊れるかもしれないtry-errorを確認する必要があります。 tryCatch()でもラップできますが、safely()の方法はちょっときれいです。

+1

'dt'も組み込み関数の名前です!!愚かなt-分布。私は 'DT'を好む – MichaelChirico

+0

ですが、少なくとも私の使用法(:-)では、Student tディストリビューションを使用するよりデータを転置したいと思うはずです – hrbrmstr

関連する問題