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

How to turn formula to variables for use with fastLm function in R

出于性能原因,我正在尝试使用函数 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 

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

y - a vector containing the explained variable.

通过使用 dt[,1]drop = FALSE in data.table which returns a data.table with single column。相反,如果我们想要一个向量,请使用 [[ 来提取列

fastLm(X = dt[, 2:3], y = dt[[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)))