【问题标题】:Pass variables in function to data.table for lm()将函数中的变量传递给 lm() 的 data.table
【发布时间】:2020-02-13 20:21:28
【问题描述】:

我想创建一个函数来在所有 data.table 列上运行 lm() 但指定从属 (x) 和按列。将 data.table、x 和 by 参数传递给函数。

我正在使用 David Arenburg 的 data.table [解决方案][1] 和 lapply() 来计算 lm() 并尝试使用 deparse() 和替代 () 将变量传递给函数,但没有成功。

下面是所需 data.table 结果的 MWE 和我的函数尝试,尝试将参数作为变量而不是引用的字符串传递。

我认为这涉及非标准评估(我确实阅读了 Advanced R 中的 NSE,但我的理解并不完全)。

感谢任何帮助!

library(data.table)

set.seed(123)

# Sample dataset
data1 <- data.table(colA = 1:10,
                    colB = runif(10),
                    colC = runif(10),
                    colD = rep(c("apples", "bananas"),5))

# Desired functionality with .SDcols and by
works <- data1[, .(lm_results = lapply(.SD, function(x) {
  lm_summary = summary(lm(colA ~ x))})),
  .SDcols = -c("colA"),
  by = .(colD)]


# attempted function
fun1 <- function(dt, y, by_col) {

  x <- dt[, .(lm_results = lapply(.SD, function(x) {
    summary(lm(substitute(y) ~ x))})),
    .SDcols = -c(deparse(substitute(y)),),
    by = .(substitute(by_col))]

  return(x)
}

fails <- fun1(data1, colA, colD)
#> Error in `[.data.table`(dt, , .(lm_results = lapply(.SD, function(x) {: column or expression 1 of 'by' or 'keyby' is type symbol. Do not quote column names. Usage: DT[,sum(colC),by=list(colA,month(colB))]

reprex package (v0.3.0) 于 2019 年 10 月 16 日创建

【问题讨论】:

  • 我认为.() 的魔法比平时更神秘。 by 可以接受字符串,所以不妨试试by = deparse(substitute(by_col))
  • 嗯,运气不好。有一个很好的错误消息建议使用by = eval(deparse(substitute())),但这对我也不起作用。
  • 好吧,坏消息是,如果您更改为 by = by_col 并使用带引号的列名,这应该可以工作,但另一部分有错误:Error in c(deparse(substitute(y)), ) : argument 2 is empty
  • 是的,我尝试了几种不同的方法,包括将公式参数作为字符串传递给lm,以及传递变量的 NSE 的不同变体。在函数中,如果您删除 by 并将 lm(substitute(y) ~ x) 更改为 lm(colA ~ x) 它可以工作,所以我猜有一个起点。

标签: r function data.table lm


【解决方案1】:

使用Pass variable name as argument inside data.table 中的quotesubstitute 调整您的lm 公式和.SDcols

fun1 <- function(dt, y, by_col) {
    expr <- quote(dt[, 
        .(lm_results=lapply(.SD, function(x) summary(lm(Y ~ x)))),
        .SDcols=sdcols,
        by=byexpr])
    eval(do.call(substitute, list(expr, 
        list(sdcols=substitute(!y), Y=as.name(y), byexpr=substitute(by_col)))))
}

fun1(data1, "colA", colD)

不酷的是colA 需要作为字符串传入。

输出:

      colD   lm_results
1:  apples <summary.lm>
2:  apples <summary.lm>
3: bananas <summary.lm>
4: bananas <summary.lm>

【讨论】:

  • 谢谢!为什么使用quote 而不是substitute 来创建expr?我也不太清楚eval 部分。我读到quoteeval 是相反的,它们相互剥离。所以eval 评估do.call,它调用substitute 作为函数,你已经传递了一个带有expr 的列表,然后是带有expr 中变量的第二个列表。它如何知道将list(sdcols=substitue(!y).... 传递给list(expr, ...) 以及如何将它们作为多个参数传递给substitute?对于这些基本问题,我很抱歉...谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-13
  • 1970-01-01
  • 2012-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多