如何将公式转换为变量以与 R 中的 fastLm 函数一起使用

Posted

技术标签:

【中文标题】如何将公式转换为变量以与 R 中的 fastLm 函数一起使用【英文标题】:How to turn formula to variables for use with fastLm function in R 【发布时间】:2022-01-13 15:31:14 【问题描述】:

出于性能原因,我正在尝试使用函数 RcppArmadillo::fastLM 而不是 lm。 这是我对lm的函数调用

test_dt = structure(list(A= c(168.08, 166.65, 167.52, 167.16, 165.77, 
167.65, 169.84, 170.45, 171.29, 173.15, 174.12, 174.45, 174.18, 
172.92, 174.5, 173.94, 172.61, 168.74, 167.28, 167.12), `B` = c(1801.599976, 
1783, 1795.099976, 1788.699951, 1763.599976, 1793, 1816.400024, 
1827.400024, 1830.199951, 1847.599976, 1863.199951, 1867.900024, 
1866.099976, 1853.599976, 1869.699951, 1861, 1851.199951, 1806, 
1783.5, 1784.099976)), row.names = c(NA, -20L), class = c("data.table", 
"data.frame"))

coef(lm(A ~ B + 0,data = test_dt))[1]

> 0.0934728 

由于 lm 大部分时间都在解释公式,所以我不想使用公式。相反,我想把它变成一些东西-

RcppArmadillo::fastLM(X = test_dt$B + 0, y = test_dt$A)

但我不知道如何添加+ 0,如公式所示。

我已经尝试了以下

library(data.table)
dt = copy(test_dt)
dt[, C := 0]
coef(RcppArmadillo::fastLm(X = dt[,2:3], y = dt[,1]))[[1]]

但这会出错。

Error in fastLm.default(X = dt[, 2:3], y = dt[, 1]) : 
  (list) object cannot be coerced to type 'double'

有人可以告诉我将公式A ~ B + 0 转换为变量Xy 以用于fastLm 函数的正确方法吗?

这是性能结果。

 microbenchmark::microbenchmark(
  formula = coef(lm(A ~ B + 0, dt))[1],
  fastLm = with(dt, coef(RcppArmadillo::fastLm(B, A)))[1],
  flm = with(dt, collapse::flm(A, cbind(B)))[1],
  times = 100)
Unit: microseconds
    expr      min       lq       mean    median        uq      max neval cld
 formula 1157.822 1173.249 1191.57071 1183.0080 1197.5560 1714.430   100   c
  fastLm  219.785  228.086  240.30415  235.2545  244.7465  405.353   100  b 
     flm   67.595   71.902   76.91765   74.7790   77.2050  228.320   100 a 

【问题讨论】:

你能不能试试公式法ie。 fastLm(A ~ B + 0, data = dt) 公式方法工作正常。唯一的问题是使用公式要慢 3 倍。 在第一个公式中您使用的是A ~ B + 0,但在第二个公式中您使用的是y 作为B,这是一个错字 是的,这是一个错字,我已经更正了。谢谢。 你需要fastLm(X = dt[, 2:3], y = dt[[1]]) 【参考方案1】:

fastLm默认方法的第一个参数是模型矩阵。它应该有一列 1 来表示截距,如果没有,则没有截距。

这些给出了相同的答案,不使用拦截:

coef(lm(A ~ B + 0, test_dt))[1]
with(test_dt, coef(fastLm(B, A)))

这些使用截距给出相同的答案:

coef(lm(A ~ B, test_dt))
with(test_dt, coef(fastLm(cbind(1, B), A)))

【讨论】:

谢谢@Grothendieck,它运行良好。我已经分享了上面的性能结果。 你也可以试试collapse包中的flm。它使用与 fastLm 相同的参数,但顺序相反,它只返回系数,因此不使用 coef。 感谢您的指点。我试过library(collapse) with(dt, collapse::flm(X = B, y = A, method = "lm")),但它抛出错误if (n != NROW(y)) stop("NROW(y) must match nrow(X)")。似乎在flm 函数内部dim(dt$A)nrow(dt$B) 都失败了。 使用问题中的 test_dt 这两个都对我有用:library(collapse); with(test_dt, flm(A, cbind(B))) - 似乎 B 不能是向量,但必须是矩阵,并使用相同的库语句:with(test_dt, flm(A, cbind(1, B))) 哇,flm 更快了。我已经更新了性能结果。非常感谢!【参考方案2】:

y 应该是一个向量。根据?fastLm

y - 包含解释变量的向量。

通过使用dt[,1]data.table 中的drop = FALSE 返回具有单列的data.table。相反,如果我们想要一个向量,请使用[[ 来提取列

fastLm(X = dt[, 2:3], y = dt[[1]])

【讨论】:

有没有办法消除警告? solve(): system is singular; attempting approx solution @Saurabh 当你说删除警告时,你想要suppressWarnings 否 :),我的意思是在调用 fastLm 时我做错了什么。我尝试将 X 转换为矩阵,但仍然存在错误。

以上是关于如何将公式转换为变量以与 R 中的 fastLm 函数一起使用的主要内容,如果未能解决你的问题,请参考以下文章

请解释我们如何将因子变量转换为 R 中的数字

如何将方程转换为单个变量的公式?

如何将整数转换为R中的分类数据?

将PB中的枚举型转化数值型

如何减少R中逻辑回归模型中的分类变量

将多个分类变量转换为R中的因子