循环内的线性模型(用于子集数据的循环)

Linear model within a loop (loop used to subset data)

我有(我认为应该是)R 中的一个直接问题,似乎无法让它工作。希望能帮到你。

我有一个数据框,例如:

x  y  z
1  2  a
2  3  a
3  4  a
4  5  b
5  6  b
6  7  b      etc...

我正在为每个 z 值子集(例如 a、b...)拟合一个线性模型 (y ~ x) 并提取梯度。

当我 select 'a' 使用 with 语句时它有效:

coef(with(subset(data.frame, z == "a"), {lm(y ~ x)
}))[2]

但我的问题是我在 Z 列中有超过 1000 个唯一值。所以我尝试设置一个循环(我知道 R 用户讨厌循环!)依次对 z 的每个值执行此操作,并 return 数据框中的结果。代码是:

gradient.lm = NULL

unique.z <- as.matrix((unique(data.frame$z)))
count.z <- nrow(unique.z)

for (i in 1:count.z) {
  gradient.lm[i] = coef((with(subset(data.frame, z == [i]), {lm(y ~ z)
  })))[2]
}

但这不起作用,并给我错误代码:

> for (i in 1:count.z) {
+   activity.lm[i] = coef((with(subset(data.frame, z == [i]), {lm(y ~ x)
Error: unexpected '[' in:
"for (i in 1:count.z) {
  activity.lm[i] = coef((with(subset(data.frame, z == ["
>   })))[2]
Error: unexpected '}' in "  }"
> }
Error: unexpected '}' in "}"

我的猜测是它没有意识到 with 函数中有一个 [i]。

我找不到实现此功能的方法,也找不到其他方法。如果您有任何建议,我们将不胜感激。

我强烈推荐 dplyrbroom 包解决方案:

set.seed(44)

dt = data.frame(x = rnorm(40, 5, 5),
                y = rnorm(40, 3, 4),
                z = rep(c("a","b"), 20))

library(dplyr)
library(broom)

dt %>%
  group_by(z) %>%            # group by column z
  do(tidy(lm(y~x, data=.)))  # for each group create model using corresponding x and y values

# Source: local data frame [4 x 6]
# Groups: z [2]
# 
#        z        term    estimate std.error  statistic    p.value
#   (fctr)       (chr)       (dbl)     (dbl)      (dbl)      (dbl)
# 1      a (Intercept)  3.54448459 1.8162699  1.9515186 0.06673401
# 2      a           x -0.18140655 0.2260252 -0.8025944 0.43267918
# 3      b (Intercept)  1.69024601 1.1960922  1.4131402 0.17467413
# 4      b           x  0.02647677 0.1914492  0.1382966 0.89154143

您可以提取您想要的 lm 输出的任何信息。

这似乎有效:

unique_z = unique(df$z)
coef_vec = vector(mode = "list", length = length(unique_z))

coef_vec[1] = 
for (i in unique_z){
  coef_vec[i] = 
    coef(
      with(
        subset(df, z==i), 
      {lm(y~x)}))[2]
}

print(coef_vec)

Cleary coef_vec[i] 对应于 unique_z[i] 中的 z 值,因此您的系数与其 z 值相匹配。

在 base-R 中,为您提供一个仅包含您显然感兴趣的梯度的命名向量:

gradient.lm <- unlist(lapply(split(df,df$z),function(chunk){
  return(coef(lm(y~x, data=chunk))[[2]])
}))