【问题标题】:Linear model within a loop (loop used to subset data)循环内的线性模型(用于子集数据的循环)
【发布时间】:2015-09-09 13:37:03
【问题描述】:

我在 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)并提取梯度。

当我使用 with 语句选择“a”时,它可以工作:

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

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

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]。

我找不到实现这项工作的方法,或者想出另一种方法。如果您有任何建议,我们将不胜感激。

【问题讨论】:

  • 使用z == unique.z[i] 而不是z == [i]
  • (将变量命名为函数通常是不好的做法 (data.frame))

标签: r loops gradient subset lm


【解决方案1】:

我强烈推荐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 输出的任何信息。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • Heroka,这似乎很完美。非常感谢!!
    【解决方案3】:

    这似乎有效:

    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)
    

    清晰的coef_vec[i] 对应于unique_z[i] 中的z 值,因此您的系数与它们的z 值匹配。

    【讨论】:

    • 您的解决方案没有返回或分配任何内容。
    • @Heroka 你可以很容易地做到这一点,不是吗?如果你愿意,我会修改它,把它全部放在一个向量中。
    猜你喜欢
    • 2019-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-14
    • 2023-03-04
    • 2013-11-21
    相关资源
    最近更新 更多