R 避免将函数参数包装在“中”;引号();在函数中使用data.table时

R 避免将函数参数包装在“中”;引号();在函数中使用data.table时,r,data.table,R,Data.table,我有一个函数,create.summary,当传递一个列名时,它会按年份和月份汇总该列的值。注意在数据表的j表达式中使用了eval() create.summary <- function(full.panel.df, outcome.name){ df.apps <- data.table(full.panel.df)[, list( Y = mean(eval(outcome.name)),

我有一个函数,
create.summary
,当传递一个列名时,它会按年份和月份汇总该列的值。注意在数据表的
j
表达式中使用了
eval()

create.summary <- function(full.panel.df, outcome.name){
    df.apps <- data.table(full.panel.df)[, list(
                                        Y = mean(eval(outcome.name)),
                                        se = sd(eval(outcome.name))/sqrt(.N)
                                        ),
                                by = list(month, year, trt)]
    return df.apps
}

create.summary尝试使用
get
而不是
eval

create.summary <- function(full.panel.df, outcome.name){
    df.apps <- data.table(full.panel.df)[, list(
                                        Y = mean(get(outcome.name)),
                                        se = sd(get(outcome.name))/sqrt(.N)
                                        ),
                                by = list(month, year, trt)]
    return df.apps
}

create.summary尝试使用
get
而不是
eval

create.summary <- function(full.panel.df, outcome.name){
    df.apps <- data.table(full.panel.df)[, list(
                                        Y = mean(get(outcome.name)),
                                        se = sd(get(outcome.name))/sqrt(.N)
                                        ),
                                by = list(month, year, trt)]
    return df.apps
}
create.summary为了我(希望还有其他人)的缘故,我已经根据不同的行为排列了我的答案和@GSee、@BrodieG的答案。至少我觉得这个比较有用

对于:
create.summary(df,小时收入)
  • eval
    更改为
    evalq
    ,在这种情况下显然是最简单的

    从帮助文件:

    evalq表单相当于eval(quote(expr),…)。eval在将其传递给计算器之前,先计算当前作用域中的第一个参数:evalq避免了这种情况

您的功能变为:

create.summary <- function(full.panel.df, outcome.name){
    df.apps <- data.table(full.panel.df)[, list(
                                        Y = mean(evalq(outcome.name)),
                                        se = sd(evalq(outcome.name))/sqrt(.N)
                                        ),
                                by = list(month, year, trt)]
    return df.apps
}
create.summary <- function(full.panel.df, outcome.name){
    df.apps <- data.table(full.panel.df)[, list(
                                        Y = mean(get(outcome.name)),
                                        se = sd(get(outcome.name))/sqrt(.N)
                                        ),
                                by = list(month, year, trt)]
    return df.apps
}
create.summary <- function(full.panel.df, outcome.name){
    df.apps <- data.table(full.panel.df)[, list(
                                        Y = mean(eval(parse(text=outcome.name))),
                                        se = sd(eval(parse(text=outcome.name)))/sqrt(.N)
                                        ),
                                by = list(month, year, trt)]
    return df.apps
}

对于:
create.summary(df,“小时收入”)
  • get()
    搜索该名称的对象;它比
    parse(text=)
您的功能变为:

create.summary <- function(full.panel.df, outcome.name){
    df.apps <- data.table(full.panel.df)[, list(
                                        Y = mean(evalq(outcome.name)),
                                        se = sd(evalq(outcome.name))/sqrt(.N)
                                        ),
                                by = list(month, year, trt)]
    return df.apps
}
create.summary <- function(full.panel.df, outcome.name){
    df.apps <- data.table(full.panel.df)[, list(
                                        Y = mean(get(outcome.name)),
                                        se = sd(get(outcome.name))/sqrt(.N)
                                        ),
                                by = list(month, year, trt)]
    return df.apps
}
create.summary <- function(full.panel.df, outcome.name){
    df.apps <- data.table(full.panel.df)[, list(
                                        Y = mean(eval(parse(text=outcome.name))),
                                        se = sd(eval(parse(text=outcome.name)))/sqrt(.N)
                                        ),
                                by = list(month, year, trt)]
    return df.apps
}

为了我(希望还有其他人)的缘故,我已经根据不同的行为排列了我的答案和@GSee,@BrodieG的答案。至少我觉得这个比较有用

对于:
create.summary(df,小时收入)
  • eval
    更改为
    evalq
    ,在这种情况下显然是最简单的

    从帮助文件:

    evalq表单相当于eval(quote(expr),…)。eval在将其传递给计算器之前,先计算当前作用域中的第一个参数:evalq避免了这种情况

您的功能变为:

create.summary <- function(full.panel.df, outcome.name){
    df.apps <- data.table(full.panel.df)[, list(
                                        Y = mean(evalq(outcome.name)),
                                        se = sd(evalq(outcome.name))/sqrt(.N)
                                        ),
                                by = list(month, year, trt)]
    return df.apps
}
create.summary <- function(full.panel.df, outcome.name){
    df.apps <- data.table(full.panel.df)[, list(
                                        Y = mean(get(outcome.name)),
                                        se = sd(get(outcome.name))/sqrt(.N)
                                        ),
                                by = list(month, year, trt)]
    return df.apps
}
create.summary <- function(full.panel.df, outcome.name){
    df.apps <- data.table(full.panel.df)[, list(
                                        Y = mean(eval(parse(text=outcome.name))),
                                        se = sd(eval(parse(text=outcome.name)))/sqrt(.N)
                                        ),
                                by = list(month, year, trt)]
    return df.apps
}

对于:
create.summary(df,“小时收入”)
  • get()
    搜索该名称的对象;它比
    parse(text=)
您的功能变为:

create.summary <- function(full.panel.df, outcome.name){
    df.apps <- data.table(full.panel.df)[, list(
                                        Y = mean(evalq(outcome.name)),
                                        se = sd(evalq(outcome.name))/sqrt(.N)
                                        ),
                                by = list(month, year, trt)]
    return df.apps
}
create.summary <- function(full.panel.df, outcome.name){
    df.apps <- data.table(full.panel.df)[, list(
                                        Y = mean(get(outcome.name)),
                                        se = sd(get(outcome.name))/sqrt(.N)
                                        ),
                                by = list(month, year, trt)]
    return df.apps
}
create.summary <- function(full.panel.df, outcome.name){
    df.apps <- data.table(full.panel.df)[, list(
                                        Y = mean(eval(parse(text=outcome.name))),
                                        se = sd(eval(parse(text=outcome.name)))/sqrt(.N)
                                        ),
                                by = list(month, year, trt)]
    return df.apps
}


和另一个使用
替换
获取

create.summary <- function(full.panel.df, outcome.name){
  out.name.quoted <- as.character(substitute(outcome.name))
  df.apps <- data.table(full.panel.df)[, list(
    Y = mean(get(out.name.quoted)),
    se = sd(get(out.name.quoted))/sqrt(.N)
    ),
    by = list(month, year, trt)
  ]
  df.apps
}
有了一些数据:

df <- data.frame(month=month.abb, year=rep(2000:2005, each=24), trt=c("one", "two"), a=runif(6 * 12), b=runif(6 * 12))

df和另一个使用
substitute
get

create.summary <- function(full.panel.df, outcome.name){
  out.name.quoted <- as.character(substitute(outcome.name))
  df.apps <- data.table(full.panel.df)[, list(
    Y = mean(get(out.name.quoted)),
    se = sd(get(out.name.quoted))/sqrt(.N)
    ),
    by = list(month, year, trt)
  ]
  df.apps
}
有了一些数据:

df <- data.frame(month=month.abb, year=rep(2000:2005, each=24), trt=c("one", "two"), a=runif(6 * 12), b=runif(6 * 12))

df如果您有一个名为“system(rm-rf./)”的列会怎么样?@GSee oy。这会很糟糕。我从未想过这一点(实际上我不知道
get()
(因此+1).我正试图更好地了解R中的非标准评估任何我可以指向的资源?ps.我应该删除这个答案吗?我不认为这对于用户在自己的终端上以自己的权限运行的函数来说有什么大不了的,这通常是大多数R包的情况。毕竟,他们可以只键入“炸毁我自己系统的命令”,而不是将其传递给第三方函数。如果您从web捕获输入,然后在您的服务器上运行它,则情况就不同了。如果您有一个名为“system(rm-rf./)”的专栏会怎么样?@GSee oy。这将很糟糕。我从未想过这一点(实际上我不知道
get()
(因此+1).我正试图更好地了解R中的非标准评估任何我可以指向的资源?ps.我应该删除这个答案吗?我不认为这对于用户在自己的终端上以自己的权限运行的函数来说有什么大不了的,这通常是大多数R包的情况。他们毕竟可以键入“命令“炸毁我自己的系统”,而不是将其传递给第三方函数。如果您从web捕获输入,然后在服务器上运行它,则情况就不同了。好的,除了OP说“我希望用户能够以字符串形式调用此函数:create.summary(df,“hourly_-earning”)“@GSee,我认为OP所说的是相对于
quote
变量名的需要而言的(也就是说,使用“var.name”比
quote(var.name)
)更可取)。对于OP的“var.name”这一点我并不清楚。”显然优于
var.name
。后者是许多用户在使用
subset
等时所熟悉的,因此它似乎是一种合理的替代方法。我不认为这优于字符版本。好的,除了OP说“我希望用户能够使用列名作为字符串调用此函数:create.summary(df,“hourly_-earnings”)”@GSee,我认为OP所说的是相对于变量名的需要而言的(也就是说,使用“var.name”比使用
quote(var.name)
)对我来说,“var.name”明显优于
var.name
。后者是许多用户在使用
子集
等时所熟悉的,因此它似乎是一种合理的替代方法。我不认为这比字符版本更优越。