将多个变量输入到 R 函数中

Posted

技术标签:

【中文标题】将多个变量输入到 R 函数中【英文标题】:Enter multiple variables into an R function 【发布时间】:2022-01-12 18:25:50 【问题描述】:

我想,并且我想将它们全部输入 table1() 函数 ==> 类似于这一行 tab<-table1(~ var1+var2+ var3+...+varN|group, data=data)

library(table1)
dataset<-data.frame(ID=c(1,1,2,2,3,3,4,4),group=c("gp1","gp2","gp1","gp2","gp1","gp2","gp1","gp2"),
                 col1=c(0,1,1,1,0,1,1,0),col2=c(0,0,1,1,1,1,0,0),col3=c(1,0,1,0,1,1,1,0))


print.f <- function(data,var1,...,group)
  tab<-table1(~ var1+...|group, data=data)
  tab


print.f(data,var1,var2,var3,group=group)

print.f(dataset,col1,col2,col3)

例如,如果我有一个包含 3 列以上的数据集,并且我想查看它们的输出,我该如何输入所有这些列?

【问题讨论】:

好的,那么当你尝试的时候发生了什么?有什么问题? @camile,我如何在 table1() 中输入我想要的变量数?我对帖子进行了编辑以使我的问题更清楚 adv-r.hadley.nz/functions.html#fun-dot-dot-dot 【参考方案1】:

将公式创建为字符向量,转换为公式类并运行 table1。在示例中,我们展示了几种使用 print.f 或直接使用 table1 创建相同输出的方法。

print.f <- function(data, ..., group) 
  v <- paste(c(...), collapse = "+")
  if (!missing(group)) v <- paste(v, "|", group)
  fo <- as.formula(paste("~", v))
  table1(fo, data = data)


library(table1)

print.f(dataset, "col1", "col2", "col3", group = "group")

print.f(dataset, c("col1", "col2", "col3"), group = "group")
print.f(dataset, grep("col", names(dataset), value = TRUE), group = "group")
print.f(dataset, names(dataset)[2:4], group = "group")

print.f(dataset[-1], ".", group = "group")
print.f(dataset, ". - ID", group = "group")

table1(~ . | group, dataset[-1])
table1(~ . - ID | group, dataset)

【讨论】:

非常漂亮!就我而言,我对一种面向语言的方法(而不是带有pasted 字符串的方法)很感兴趣,在此过程中,我想出了op_literal() 函数,如above 所示。你知道是否已经存在类似的功能吗?我无法找到任何东西,所以我必须自己制作。 @Greg, reformulate(c("a", "b", "c"))[[2]] 提供与 op_literal(`+`, a, b, c) 相同的输出 太棒了!对于任意大的操作数集,是否有一个函数可以扩展到任何二元运算符?还是只有+ 用于公式? 我不这么认为。重新制定旨在与回归公式一起使用。 很高兴知道!如果我可以让op_literal() 与像dplyr::`%&gt;%` 这样的打包操作数很好地配合,这些操作数是完全合格的,但不能强制转换为symbol,那么我实际上可能有一些东西!【参考方案2】:

这是一个操纵语言而不是字符串的解决方案。您和其他人将来可能还会发现 op_literal() 很有用。

解决方案

助手:op_literal()

这个辅助函数 op_literal() 实际上操纵 R 语言本身在 许多 操作数中重复使用像 + 这样的二元运算符...即使二元运算符通常只接受 两个 操作数。调用op_literal(`+`, w, x, y, z) 实际上会在此处生成expressionw + x + y + z

# Helper function to arbitrarily repeat a binary operation (like '+').
op_literal <- function(op, ...) 
    # Capture the operator as a symbol.
    op_sym <- rlang::ensym(op)
    # Count the operands.
    n_dots <- rlang::dots_n(...)
    
    # Recursive case: a binary operator cannot handle this many arguments.
    if(n_dots > 2) 
        # Split off the final operand.
        dots <- rlang::exprs(...)
        dots_last <- dots[[n_dots]]
        dots <- dots[-n_dots]
        
        # Perform recursion for the remaining operands.
        op_left <- rlang::inject(op_literal(
            op = !!op_sym,
            ... = !!!dots
        ))
        
        # Assemble recursive results into the full operation.
        substitute(op(op_left, dots_last))
    
    # Base case: the binary operator can handle 2(-) arguments.
    else 
        substitute(op(...))
    

注意

由于op_literal() 生成expression,如果您想要结果,您仍然需要evaluate:

op_exp <- op_literal(`+`, 1, 2, 3, 4)
op_exp
#> 1 + 2 + 3 + 4

eval(op_exp)
#> [1] 10

自定义函数:print.f()

接下来,这个自定义的print.f() 然后利用op_literal() 组装公式:

# Your custom 'print.f()' function.
print.f <- function(data, var1, ..., group) 
    # Capture the core variables as symbols.
    group_var <- rlang::ensym(group)
    other_vars <- rlang::ensym(var1)
    
    # Count the additional variables.
    n_dots <- rlang::dots_n(...)
    
    # Append those other variables if they exist.
    if(n_dots > 0) 
        other_vars <- rlang::inject(op_literal(op = `+`, !!other_vars, ...))
    
    
    # Assemble the formula.
    formula_exp <- rlang::inject(~ !!other_vars | !!group_var)
    
    # Generate the table according to that formula.
    table1::table1(
        formula_exp,
        data = data
    )

结果

鉴于您的dataset 在此处转载

dataset <- data.frame(
    ID = c(1, 1, 2, 2, 3, 3, 4, 4),
    group = c("gp1", "gp2", "gp1", "gp2", "gp1", "gp2", "gp1", "gp2"),
    col1 = c(0, 1, 1, 1, 0, 1, 1, 0),
    col2 = c(0, 0, 1, 1, 1, 1, 0, 0),
    col3 = c(1, 0, 1, 0, 1, 1, 1, 0)
)

您致电print.f()

print.f(dataset, col1, col2, col3, group = group)

应该产生以下可视化:

注意

就目前而言,您已经在函数头的end 处定义了group 参数。这意味着如果您尝试像这样调用print.f()

print.f(data = dataset, var = col1, col2, col3, group)

然后你会得到一个错误:如果没有group = 规范,最终变量会与col2col3 混为一谈,都在... 的保护伞下。这会产生一个错误的公式:

~ col1 + col2 + col3 + group | 

为避免每次都必须输入group = 的痛苦,您可以简单地将其重新定位在... 之前,如下所示:

print.f <- function(data, group, var1, ...) 
  #                       ^^^^^

完成此操作后,以下调用将按您的预期工作:

print.f(dataset, group, col1, col2, col3)

【讨论】:

以上是关于将多个变量输入到 R 函数中的主要内容,如果未能解决你的问题,请参考以下文章

R从字符向量输入名称到函数公式语句

在 R 中绘制多个变量函数

R语言paste函数paste0函数将多个输入组合成字符串实战

R代码可检测多个患者随时间变化的变量

R用户定义函数,返回多个类型对象

R如何将变量名称列表一起传递给函数