如何将公式转换为变量以与 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
转换为变量X
和y
以用于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 函数一起使用的主要内容,如果未能解决你的问题,请参考以下文章