我有一个包含 45k 多行的数据框,其中包含 ID
SE441
和年份 NUM_EXPLOTACION
的变量 ANO
的值。
我想计算每年和上一年之间每个ID的变量差异。问题是某些 ID 缺少年份,因此使用
lag
函数似乎不是我的解决方案。
我想要实现的一个例子是:
ANO NUM_EXPLOTACION SE441 diff
2017 657 12 NA
2018 657 15 3
2020 657 13 NA
2018 123 1 NA
2019 123 4 3
2020 123 0 -4
示例数据框:
macro <- data.frame(ANO=c(2017, 2018, 2020, 2018, 2019, 2020),
NUM_EXPLOTACION=c(657, 657, 657, 123, 123, 123),
SE441=c(12, 15, 13, 1, 4, 0))
这是一个嵌套的 for 循环,我相信它可以完成这项工作,但它花费的时间太长,因此不可行:
for (i in min(macro$NUM_EXPLOTACION):max(macro$NUM_EXPLOTACION)) {
for (j in min(macro$ANO) + 1:max(macro$ANO)) {
macro$diff[macro$NUM_EXPLOTACION == i & macro$ANO == j] <-
if (length(macro$SE441[macro$NUM_EXPLOTACION == i & macro$ANO == j - 1])) {
macro$SE441[macro$NUM_EXPLOTACION == i & macro$ANO == j] -
macro$SE441[macro$NUM_EXPLOTACION == i & macro$ANO == j - 1]
} else NA
}
}
在上面的代码中,我使用
min(macro$ANO) + 1
来避免尝试使用不存在的值(第一个值之前没有上一年)进行数学计算,并且 if(length(...))
仅在存在匹配的 ID 和上一年时才执行该函数。
有什么想法吗?
您可以使用
complete()
中的 tidyr
来填充 SE441
中缺失值的所有年份 ID 组合,然后滞后应该起作用:
macro <- data.frame(ANO=c(2017,2018,2020,2018,2019,2020),
NUM_EXPLOTACION=c(657,657,657,123,123,123),
SE441=c(12,15,13,1,4,0))
library(tidyverse)
macro %>%
mutate(orig = 1) %>%
complete(ANO, NUM_EXPLOTACION, fill=list(SE441 = NA, orig=0)) %>%
arrange(NUM_EXPLOTACION, ANO) %>%
group_by(NUM_EXPLOTACION) %>%
mutate(diff = SE441-lag(SE441)) %>%
filter(orig==1)
#> # A tibble: 6 × 5
#> # Groups: NUM_EXPLOTACION [2]
#> ANO NUM_EXPLOTACION SE441 orig diff
#> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 2018 123 1 1 NA
#> 2 2019 123 4 1 3
#> 3 2020 123 0 1 -4
#> 4 2017 657 12 1 NA
#> 5 2018 657 15 1 3
#> 6 2020 657 13 1 NA
创建于 2024-05-23,使用 reprex v2.0.2
一种选择是
merge
与 expand.grid
并使用 diff
按组计算 ave
。
> macro |>
+ merge(expand.grid(ANO=min(macro$ANO):max(macro$ANO),
+ NUM_EXPLOTACION=unique(macro$NUM_EXPLOTACION)), all=TRUE) |>
+ sort_by(~ NUM_EXPLOTACION + ANO) |> ## requires R >= 4.4.0
+ transform(diff=ave(SE441, NUM_EXPLOTACION, FUN=\(x) c(NA, diff(x))))
ANO NUM_EXPLOTACION SE441 diff
1 2017 123 NA NA
3 2018 123 1 NA
5 2019 123 4 3
7 2020 123 0 -4
2 2017 657 12 NA
4 2018 657 15 3
6 2019 657 NA NA
8 2020 657 13 NA
使用连接的方法。首先加入已完成的年份,然后在
SE441上使用
diff
,最后重新加入原始年份以删除缺失的年份
library(dplyr)
full_join(macro, macro %>%
reframe(ANO = min(ANO):max(ANO), .by = NUM_EXPLOTACION),
by = c("ANO", "NUM_EXPLOTACION")) %>%
arrange(NUM_EXPLOTACION, ANO) %>%
mutate(diff = c(NA, diff(SE441)), .by = NUM_EXPLOTACION) %>%
right_join(macro, by = c("ANO", "NUM_EXPLOTACION", "SE441"))
ANO NUM_EXPLOTACION SE441 diff
1 2018 123 1 NA
2 2019 123 4 3
3 2020 123 0 -4
4 2017 657 12 NA
5 2018 657 15 3
6 2020 657 13 NA