[英]Row-wise linear regression and prediction in R
我有两个国家数据集,第一个从 2012 年到 2020 年,看起来像这样:
> head(y)
Country 2012 2013 2014 2015 2016 2017 2018 2019 2020
1 Afghanistan 0 0.0 0 0 0.00 4.00 7.00 22.00 26.00
2 Albania 0 0.0 0 35 80.20 85.30 85.50 95.00 98.38
3 Algeria 0 0.0 0 0 3.62 30.49 52.84 53.63 76.18
4 Andorra 50 50.0 50 50 50.00 85.00 85.00 85.00 85.00
5 Angola 7 7.0 7 7 8.00 8.00 8.00 18.00 30.00
6 Antigua and Barbuda 65 78.6 80 98 99.00 99.00 99.00 99.00 99.00
第二个是从 2012 年到 2030 年,看起来像这样:
> head(x)
CountryName CountryCode CountryCodeID ProductID Y2012 Y2013 Y2014 Y2015 Y2016 Y2017 Y2018 Y2019 Y2020 Y2021 Y2022 Y2023 Y2024 Y2025 Y2026 Y2027 Y2028 Y2029 Y2030
1 Antigua AA 157 178271 98.000000 98.00 98.00 98.35281 99.22350 99.30797 99.38018 99.44286 99.49796 99.54694 99.59088 99.63063 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000
2 Albania AB 158 178271 99.000000 99.00 99.00 99.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000
3 Angola AG 161 178271 47.000000 53.00 46.00 60.00000 70.12252 78.48148 84.95833 89.19728 92.40534 95.10876 96.64146 97.54840 98.10920 98.46371 99.36144 99.42651 99.48353 99.53406 99.57929
4 Azerbaijan AJ 163 178271 96.500000 96.90 97.10 97.30000 98.23938 98.78344 99.10162 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000
5 Algeria AL 164 178271 1.142043 6.00 23.23 46.00000 56.33254 66.41615 75.59252 82.67079 88.15954 91.56166 94.41373 96.92251 98.01697 98.65143 99.02451 100.00000 100.00000 100.00000 100.00000
6 Armenia AM 165 178271 96.300000 97.68 98.80 99.90000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000 100.00000
我想对每个国家/地区的 2012 年至 2020 年之间的日期进行类似lm(y ~ x)
的线性回归,然后根据同一时期的x
预测 2021 年至 2030 年的y
。
谁能帮我实现这一目标? 由于我有 139 个国家(行),因此从两个数据集中提取每个国家并将它们组合在一个数据框中然后运行回归和预测是很挑剔的,更有效的方法将大有帮助。
首先,最好将你的数据转换成整齐的格式,这样每年的观察就有一行。 我将在模拟数据上进行演示:
library(dplyr)
library(tidyr)
N_COUNTRIES <- 3
YEARS <- 2012:2020
N_YEARS <- length(YEARS)
# simulate x data
countries <- LETTERS[1:N_COUNTRIES]
mat_x <- matrix(runif(N_COUNTRIES*N_YEARS, 0, 100), nrow = N_COUNTRIES)
colnames(mat_x) <- YEARS
df_x <- bind_cols(country = countries, mat_x)
# simulate y data
mat_y <- matrix(runif(N_COUNTRIES*N_YEARS, 0, 50), nrow = N_COUNTRIES)
colnames(mat_y) <- paste0("Y", YEARS)
df_y <- bind_cols(
country = countries,
some_other_column = sample(1:100, N_COUNTRIES), mat_y
)
# convert df_x to long format
df_x_long <-
df_x %>%
pivot_longer(-country, names_to = "year", values_to = "x") %>%
mutate(across(year, as.numeric))
head(df_x_long)
#> # A tibble: 6 × 3
#> country year x
#> <chr> <dbl> <dbl>
#> 1 A 2012 67.6
#> 2 A 2013 71.9
#> 3 A 2014 48.7
#> 4 A 2015 20.0
#> 5 A 2016 13.3
#> 6 A 2017 62.4
# convert df_y to long format
df_y_long <-
df_y %>%
select(country, starts_with("Y")) %>%
pivot_longer(-country, names_to = "year", values_to = "y") %>%
mutate(year = as.numeric(gsub("^Y", "", year)))
现在很容易将 x 和 y 观测值合并在一起。
# join
df_xy_long <- inner_join(df_x_long, df_y_long, by = c("country", "year"))
head(df_xy_long)
#> # A tibble: 6 × 4
#> country year x y
#> <chr> <dbl> <dbl> <dbl>
#> 1 A 2012 67.6 13.6
#> 2 A 2013 71.9 19.5
#> 3 A 2014 48.7 35.0
#> 4 A 2015 20.0 31.9
#> 5 A 2016 13.3 16.7
#> 6 A 2017 62.4 47.4
有了这个,我们可以使用tidyr::nest()
将每个国家的观察结果放入单独的盒子中,然后在每个盒子上运行lm
。
# nest and model
df_xy_nested <-
df_xy_long %>%
group_by(country) %>%
nest() %>%
rowwise() %>%
mutate(model = list(lm(y ~ x, data = data))) %>%
ungroup()
head(df_xy_nested)
#> # A tibble: 3 × 3
#> country data model
#> <chr> <list> <list>
#> 1 A <tibble [9 × 3]> <lm>
#> 2 B <tibble [9 × 3]> <lm>
#> 3 C <tibble [9 × 3]> <lm>
data
列中的每个元素都是 dataframe 本身, model
列中的每个元素都是lm
model。
df_xy_nested$data[[1]]
#> # A tibble: 9 × 3
#> year x y
#> <dbl> <dbl> <dbl>
#> 1 2012 67.6 13.6
#> 2 2013 71.9 19.5
#> 3 2014 48.7 35.0
#> 4 2015 20.0 31.9
#> 5 2016 13.3 16.7
#> 6 2017 62.4 47.4
#> 7 2018 38.1 40.9
#> 8 2019 96.1 36.6
#> 9 2020 24.8 2.57
df_xy_nested$model[[1]]
#>
#> Call:
#> lm(formula = y ~ x, data = data)
#>
#> Coefficients:
#> (Intercept) x
#> 19.3173 0.1587
您可能想像这样提取 model 系数:
df_xy_nested %>%
rowwise() %>%
mutate(
coef_intercept = model$coefficients[[1]],
coef_x = model$coefficients[[2]]
)
#> # A tibble: 3 × 5
#> # Rowwise:
#> country data model coef_intercept coef_x
#> <chr> <list> <list> <dbl> <dbl>
#> 1 A <tibble [9 × 3]> <lm> 19.3 0.159
#> 2 B <tibble [9 × 3]> <lm> 29.9 -0.161
#> 3 C <tibble [9 × 3]> <lm> 18.3 0.0427
由代表 package (v2.0.1) 于 2022 年 8 月 3 日创建
有关嵌套数据建模的更多详细信息,我建议您阅读:
关于 rowwise() 文档的一段(非常短)
R4DS中的一章(一点也不短)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.