我有50万个用户,我需要为每个用户计算线性回归(带截距)。
每个用户大约有30条记录。
我尝试使用dplyr
和lm
,这太慢了。
用户大约2秒。
df%>%
group_by(user_id, add = FALSE) %>%
do(lm = lm(Y ~ x, data = .)) %>%
mutate(lm_b0 = summary(lm)$coeff[1],
lm_b1 = summary(lm)$coeff[2]) %>%
select(user_id, lm_b0, lm_b1) %>%
ungroup()
)
我尝试使用已知更快的
lm.fit
,但它似乎与dplyr
不兼容。是否有按组进行线性回归的快速方法?
最佳答案
您可以使用基本公式来计算斜率和回归。如果您只关心这两个数字,lm
会做很多不必要的事情。在这里,我使用data.table
进行聚合,但是您也可以在base R(或dplyr
)中进行此操作:
system.time(
res <- DT[,
{
ux <- mean(x)
uy <- mean(y)
slope <- sum((x - ux) * (y - uy)) / sum((x - ux) ^ 2)
list(slope=slope, intercept=uy - slope * ux)
}, by=user.id
]
)
为500K用户产生约30磅(以秒为单位)的内容:
user system elapsed
7.35 0.00 7.36
或每个用户约15微秒。
更新:我最后写了一堆与此相关的blog posts。
并确认这按预期工作:
> summary(DT[user.id==89663, lm(y ~ x)])$coefficients
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.1965844 0.2927617 0.6714826 0.5065868
x 0.2021210 0.5429594 0.3722580 0.7120808
> res[user.id == 89663]
user.id slope intercept
1: 89663 0.202121 0.1965844
数据:
set.seed(1)
users <- 5e5
records <- 30
x <- runif(users * records)
DT <- data.table(
x=x, y=x + runif(users * records) * 4 - 2,
user.id=sample(users, users * records, replace=T)
)
关于r - 按组快速线性回归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29803993/