通过使用 data.table 在每个组中向前滚动来填充缺失值
Fill missing values by rolling forward in each group using data.table
我的目标是通过向前滚动来按组填充缺失值。
虚拟数据
library(data.table)
DT <- structure(list(CLASS = c("A", "A", "A", "A", "A", "A", "B", "B","B"),
VAL = c(NA, 1, NA, NA, 2, NA, 50, NA, 100)),
.Names = c("CLASS", "VAL"),
row.names = c(NA, -9L), class = c("data.table", "data.frame"))
> DT
CLASS VAL
1: A NA
2: A 1
3: A NA
4: A NA
5: A 2
6: A NA
7: B 50
8: B NA
9: B 100
想要的结果
CLASS VAL
1: A NA
2: A 1
3: A 1
4: A 1
5: A 2
6: A 2
7: B 50
8: B 50
9: B 100
请注意,here 的结果不适用。
1) 这会为组中的每个观察值分配第一个非缺失值
#1
DT[, VAL:= VAL[!is.na(VAL)][1L] , by = CLASS]
> DT
CLASS VAL
1: A 1
2: A 1
3: A 1
4: A 1
5: A 1
6: A 1
7: B 50
8: B 50
9: B 50
2) 如果要分配的行仅在 i
中过滤为缺失值,则在 by
中分组时无法提取任何非 NA 值。所以结果没有任何改变。
> DT[is.na(VAL), VAL:= VAL[!is.na(VAL)][1L] , by = CLASS]
> DT
CLASS VAL
1: A NA
2: A 1
3: A NA
4: A NA
5: A 2
6: A NA
7: B 50
8: B NA
9: B 100
9: B 50
3) 使用 tidyr
中的 fill()
的解决方案有效,但不幸的是使用了具有 350 万行和 200 万组的真实数据; 运行 时间约为 6 小时。所以我正在寻找更有效的 data.table
解决方案。
> DT <- DT %>% group_by(CLASS) %>% fill(VAL)
> DT
# A tibble: 9 x 2
# Groups: CLASS [2]
CLASS VAL
<chr> <dbl>
1 A NA
2 A 1.00
3 A 1.00
4 A 1.00
5 A 2.00
6 A 2.00
7 B 50.0
8 B 50.0
9 B 100
您可以使用 zoo
包中的 na.locf()
函数:
DT[, VAL:=zoo::na.locf(VAL, na.rm = FALSE), "CLASS"]
我的目标是通过向前滚动来按组填充缺失值。
虚拟数据
library(data.table)
DT <- structure(list(CLASS = c("A", "A", "A", "A", "A", "A", "B", "B","B"),
VAL = c(NA, 1, NA, NA, 2, NA, 50, NA, 100)),
.Names = c("CLASS", "VAL"),
row.names = c(NA, -9L), class = c("data.table", "data.frame"))
> DT
CLASS VAL
1: A NA
2: A 1
3: A NA
4: A NA
5: A 2
6: A NA
7: B 50
8: B NA
9: B 100
想要的结果
CLASS VAL
1: A NA
2: A 1
3: A 1
4: A 1
5: A 2
6: A 2
7: B 50
8: B 50
9: B 100
请注意,here 的结果不适用。
1) 这会为组中的每个观察值分配第一个非缺失值
#1
DT[, VAL:= VAL[!is.na(VAL)][1L] , by = CLASS]
> DT
CLASS VAL
1: A 1
2: A 1
3: A 1
4: A 1
5: A 1
6: A 1
7: B 50
8: B 50
9: B 50
2) 如果要分配的行仅在 i
中过滤为缺失值,则在 by
中分组时无法提取任何非 NA 值。所以结果没有任何改变。
> DT[is.na(VAL), VAL:= VAL[!is.na(VAL)][1L] , by = CLASS]
> DT
CLASS VAL
1: A NA
2: A 1
3: A NA
4: A NA
5: A 2
6: A NA
7: B 50
8: B NA
9: B 100
9: B 50
3) 使用 tidyr
中的 fill()
的解决方案有效,但不幸的是使用了具有 350 万行和 200 万组的真实数据; 运行 时间约为 6 小时。所以我正在寻找更有效的 data.table
解决方案。
> DT <- DT %>% group_by(CLASS) %>% fill(VAL)
> DT
# A tibble: 9 x 2
# Groups: CLASS [2]
CLASS VAL
<chr> <dbl>
1 A NA
2 A 1.00
3 A 1.00
4 A 1.00
5 A 2.00
6 A 2.00
7 B 50.0
8 B 50.0
9 B 100
您可以使用 zoo
包中的 na.locf()
函数:
DT[, VAL:=zoo::na.locf(VAL, na.rm = FALSE), "CLASS"]