运行 lm() 作用于数据框中 2 个不同变量的子集
Run lm() function over subsets of 2 different variables in data frame
我想创建一个函数(最好使用 apply
系列函数,运行 是一个 lm
函数,作用于数据框中两个独立变量的数据子集. 作为参考,我的数据目前结构如下(这是一个虚拟数据框,通常代表我正在使用的真实数据框):
District = c(rep("A", times = 25),
rep("B", times = 25),
rep("C", times = 25),
rep("D", times = 25))
Year = c(1971:1975, 1971:1975, 1971:1975, 1971:1975,
1971:1975, 1971:1975, 1971:1975, 1971:1975,
1971:1975, 1971:1975, 1971:1975, 1971:1975,
1971:1975, 1971:1975, 1971:1975, 1971:1975,
1971:1975, 1971:1975, 1971:1975, 1971:1975)
Crop = c(rep("Wheat", times = 5),
rep("Maize", times = 5),
rep("Rice", times = 5),
rep("Barley", times = 5))
set.seed(100)
Yield = rnorm(100, 2, 0.5)
df <- data.frame(District, Year, Crop, Yield)
我需要生成一个线性模型 (lm
) 预测 Yield
作为 Year
的函数,每个 Crop
在每个 District
基础。因此,我需要每个地区的小麦模型、每个地区的大麦模型等等。我需要尽可能自动化,因为我的真实数据将产生大约 7000 个线性模型。
我发现 this answer by James Bond 作为出发点非常有用。它非常优雅并使用 lapply
,如果可能的话我也想这样做(7000 个线性模型 = 非常慢)。但是,它只是对数据集中的单个列进行子集化,而我需要为每个模型对两个变量进行子集化。这是我在上述虚拟数据集上修改为 运行 的当前(非工作)代码:
df$Dist <- as.factor(df$Dist)
df$Crop <- as.factor(df$Crop)
for (i in 1:length(levels(df$Crop))) {
x <- levels(df$Crop)[i]
dat <- df[df$Crop == x, ]
out <- lapply(levels(dat$Dist), function(z) {
data.frame(District = z,
Slope = lm(Yield ~ Year, data = dat[dat$Dist == z, ])$coef[2],
Crop = x,
row.names=NULL)
})
}
do.call(rbind ,out)
不幸的是,运行上面的代码只为数据集(小麦)中的第一个 Crop
级别生成了一个模型。请参阅下面的输出:
District Slope Crop
1 A 0.03125866 Wheat
2 B -0.08108222 Wheat
3 C 0.17172314 Wheat
4 D -0.11278486 Wheat
任何能够循环遍历 Crop
和 District
变量的帮助将不胜感激。看起来我很接近,但似乎缺少有关 for 循环的一些基本知识。
如果可以将 2 个参数传递给 lapply
函数并完全避免 for
循环,那就太棒了。提前致谢!
一个选项使用 dplyr:
df_lm <- df %>%
group_by(District,Crop) %>%
do(mod = lm(Yield ~ Year,data = .))
df_coef <- df_lm %>%
do(data.frame(
District = .$District,
Crop = .$Crop,
var = names(coef(.$mod)),
coef(summary(.$mod)))
)
> df_coef
Source: local data frame [32 x 7]
Groups: <by row>
# A tibble: 32 × 7
District Crop var Estimate Std..Error t.value Pr...t..
* <fctr> <fctr> <fctr> <dbl> <dbl> <dbl> <dbl>
1 A Barley (Intercept) -407.66953514 378.49788671 -1.0770722 0.36034462
2 A Barley Year 0.20771336 0.19183872 1.0827499 0.35818046
3 A Maize (Intercept) 159.81133118 212.90233600 0.7506321 0.50738515
4 A Maize Year -0.08002266 0.10790790 -0.7415830 0.51211787
5 A Rice (Intercept) -68.01125454 117.60578244 -0.5782986 0.60361684
6 A Rice Year 0.03552764 0.05960758 0.5960255 0.59313364
7 A Wheat (Intercept) -59.61828825 134.67806297 -0.4426726 0.66972726
8 A Wheat Year 0.03125866 0.06826053 0.4579317 0.65918309
9 B Barley (Intercept) -319.99755207 57.14553545 -5.5996947 0.01125215
10 B Barley Year 0.16332436 0.02896377 5.6389189 0.01103509
# ... with 22 more rows
另一件要看的事情是 nlme 中的 lmList
函数。
我想创建一个函数(最好使用 apply
系列函数,运行 是一个 lm
函数,作用于数据框中两个独立变量的数据子集. 作为参考,我的数据目前结构如下(这是一个虚拟数据框,通常代表我正在使用的真实数据框):
District = c(rep("A", times = 25),
rep("B", times = 25),
rep("C", times = 25),
rep("D", times = 25))
Year = c(1971:1975, 1971:1975, 1971:1975, 1971:1975,
1971:1975, 1971:1975, 1971:1975, 1971:1975,
1971:1975, 1971:1975, 1971:1975, 1971:1975,
1971:1975, 1971:1975, 1971:1975, 1971:1975,
1971:1975, 1971:1975, 1971:1975, 1971:1975)
Crop = c(rep("Wheat", times = 5),
rep("Maize", times = 5),
rep("Rice", times = 5),
rep("Barley", times = 5))
set.seed(100)
Yield = rnorm(100, 2, 0.5)
df <- data.frame(District, Year, Crop, Yield)
我需要生成一个线性模型 (lm
) 预测 Yield
作为 Year
的函数,每个 Crop
在每个 District
基础。因此,我需要每个地区的小麦模型、每个地区的大麦模型等等。我需要尽可能自动化,因为我的真实数据将产生大约 7000 个线性模型。
我发现 this answer by James Bond 作为出发点非常有用。它非常优雅并使用 lapply
,如果可能的话我也想这样做(7000 个线性模型 = 非常慢)。但是,它只是对数据集中的单个列进行子集化,而我需要为每个模型对两个变量进行子集化。这是我在上述虚拟数据集上修改为 运行 的当前(非工作)代码:
df$Dist <- as.factor(df$Dist)
df$Crop <- as.factor(df$Crop)
for (i in 1:length(levels(df$Crop))) {
x <- levels(df$Crop)[i]
dat <- df[df$Crop == x, ]
out <- lapply(levels(dat$Dist), function(z) {
data.frame(District = z,
Slope = lm(Yield ~ Year, data = dat[dat$Dist == z, ])$coef[2],
Crop = x,
row.names=NULL)
})
}
do.call(rbind ,out)
不幸的是,运行上面的代码只为数据集(小麦)中的第一个 Crop
级别生成了一个模型。请参阅下面的输出:
District Slope Crop
1 A 0.03125866 Wheat
2 B -0.08108222 Wheat
3 C 0.17172314 Wheat
4 D -0.11278486 Wheat
任何能够循环遍历 Crop
和 District
变量的帮助将不胜感激。看起来我很接近,但似乎缺少有关 for 循环的一些基本知识。
如果可以将 2 个参数传递给 lapply
函数并完全避免 for
循环,那就太棒了。提前致谢!
一个选项使用 dplyr:
df_lm <- df %>%
group_by(District,Crop) %>%
do(mod = lm(Yield ~ Year,data = .))
df_coef <- df_lm %>%
do(data.frame(
District = .$District,
Crop = .$Crop,
var = names(coef(.$mod)),
coef(summary(.$mod)))
)
> df_coef
Source: local data frame [32 x 7]
Groups: <by row>
# A tibble: 32 × 7
District Crop var Estimate Std..Error t.value Pr...t..
* <fctr> <fctr> <fctr> <dbl> <dbl> <dbl> <dbl>
1 A Barley (Intercept) -407.66953514 378.49788671 -1.0770722 0.36034462
2 A Barley Year 0.20771336 0.19183872 1.0827499 0.35818046
3 A Maize (Intercept) 159.81133118 212.90233600 0.7506321 0.50738515
4 A Maize Year -0.08002266 0.10790790 -0.7415830 0.51211787
5 A Rice (Intercept) -68.01125454 117.60578244 -0.5782986 0.60361684
6 A Rice Year 0.03552764 0.05960758 0.5960255 0.59313364
7 A Wheat (Intercept) -59.61828825 134.67806297 -0.4426726 0.66972726
8 A Wheat Year 0.03125866 0.06826053 0.4579317 0.65918309
9 B Barley (Intercept) -319.99755207 57.14553545 -5.5996947 0.01125215
10 B Barley Year 0.16332436 0.02896377 5.6389189 0.01103509
# ... with 22 more rows
另一件要看的事情是 nlme 中的 lmList
函数。