使用最新非缺失行的值并应用滚动功能
Use value from latest non missing row and apply rolling function
我有
中的数据
DT <- data.frame(id=rep("A",times=10),B=1:10, C=c(NA,2:5,NA,NA,NA,NA,NA))
CT <- DT[,c(2,3)]*3
CT$id <- rep("B",times=10)
DT <- rbind(DT,CT)
我想在 C 列的 NA 中填入它的前一个值加上 B 列其他列的值的函数(忽略 C 列中的第一个 NA),例如:
DT$C[6] =DT$C[5]+DT$B[6]*0.3
DT$C[7] =DT$C[6]+DT$B[7]*0.3
DT$C[8] =DT$C[7]+DT$B[8]*0.3
等
此外,我需要通过 id 值(table 中的列 id)复制它。下面是具有三个手动计算值的示例图片。感谢您的建议!
这是 purrr
中 accumulate
的一种方法
library(data.table)
library(purrr)
setDT(DT)[, C := {i1 <- which(is.na(C))[1]
replace(C, (i1-1):.N, accumulate(B[i1:.N], ~ .x + .y * 0.3, .init = C[i1-1]))},
by = id]
# id B C
# 1: A 1 1.0
# 2: A 2 2.0
# 3: A 3 3.0
# 4: A 4 4.0
# 5: A 5 5.0
# 6: A 6 6.8
# 7: A 7 8.9
# 8: A 8 11.3
# 9: A 9 14.0
#10: A 10 17.0
#11: B 3 3.0
#12: B 6 6.0
#13: B 9 9.0
#14: B 12 12.0
#15: B 15 15.0
#16: B 18 20.4
#17: B 21 26.7
#18: B 24 33.9
#19: B 27 42.0
#20: B 30 51.0
NA单元格的填充公式相当于用na.locf
填充,加上C
中NA值对应的B
个值的cumsum的0.3倍。
因此,首先为分组向量创建一个表达式,将唯一数字与每个非 NA 和连续 NA 的每一段相关联。
rleid(seq_along(C) * !is.na(C)))
对于这些组中的每一个,计算 B * is.na(C)
的累积和向量,如果该组有一个非 NA 元素,则为 0,如果该组由连续的 NA 组成,则为 cumsum
。
这给出了以下单个语句的解决方案:
library(data.table)
library(zoo)
transform(DT, C = ave(C, id, FUN = na.locf0) +
0.3 * ave(B * is.na(C), rleid(seq_along(C) * !is.na(C)), id, FUN = cumsum))
给予:
id B C
1 A 1 NA
2 A 2 2.0
3 A 3 3.0
4 A 4 4.0
5 A 5 5.0
6 A 6 6.8
7 A 7 8.9
8 A 8 11.3
9 A 9 14.0
10 A 10 17.0
11 B 3 NA
12 B 6 6.0
13 B 9 9.0
14 B 12 12.0
15 B 15 15.0
16 B 18 20.4
17 B 21 26.7
18 B 24 33.9
19 B 27 42.0
20 B 30 51.0
我有
中的数据DT <- data.frame(id=rep("A",times=10),B=1:10, C=c(NA,2:5,NA,NA,NA,NA,NA))
CT <- DT[,c(2,3)]*3
CT$id <- rep("B",times=10)
DT <- rbind(DT,CT)
我想在 C 列的 NA 中填入它的前一个值加上 B 列其他列的值的函数(忽略 C 列中的第一个 NA),例如:
DT$C[6] =DT$C[5]+DT$B[6]*0.3
DT$C[7] =DT$C[6]+DT$B[7]*0.3
DT$C[8] =DT$C[7]+DT$B[8]*0.3
等
此外,我需要通过 id 值(table 中的列 id)复制它。下面是具有三个手动计算值的示例图片。感谢您的建议!
这是 purrr
accumulate
的一种方法
library(data.table)
library(purrr)
setDT(DT)[, C := {i1 <- which(is.na(C))[1]
replace(C, (i1-1):.N, accumulate(B[i1:.N], ~ .x + .y * 0.3, .init = C[i1-1]))},
by = id]
# id B C
# 1: A 1 1.0
# 2: A 2 2.0
# 3: A 3 3.0
# 4: A 4 4.0
# 5: A 5 5.0
# 6: A 6 6.8
# 7: A 7 8.9
# 8: A 8 11.3
# 9: A 9 14.0
#10: A 10 17.0
#11: B 3 3.0
#12: B 6 6.0
#13: B 9 9.0
#14: B 12 12.0
#15: B 15 15.0
#16: B 18 20.4
#17: B 21 26.7
#18: B 24 33.9
#19: B 27 42.0
#20: B 30 51.0
NA单元格的填充公式相当于用na.locf
填充,加上C
中NA值对应的B
个值的cumsum的0.3倍。
因此,首先为分组向量创建一个表达式,将唯一数字与每个非 NA 和连续 NA 的每一段相关联。
rleid(seq_along(C) * !is.na(C)))
对于这些组中的每一个,计算 B * is.na(C)
的累积和向量,如果该组有一个非 NA 元素,则为 0,如果该组由连续的 NA 组成,则为 cumsum
。
这给出了以下单个语句的解决方案:
library(data.table)
library(zoo)
transform(DT, C = ave(C, id, FUN = na.locf0) +
0.3 * ave(B * is.na(C), rleid(seq_along(C) * !is.na(C)), id, FUN = cumsum))
给予:
id B C
1 A 1 NA
2 A 2 2.0
3 A 3 3.0
4 A 4 4.0
5 A 5 5.0
6 A 6 6.8
7 A 7 8.9
8 A 8 11.3
9 A 9 14.0
10 A 10 17.0
11 B 3 NA
12 B 6 6.0
13 B 9 9.0
14 B 12 12.0
15 B 15 15.0
16 B 18 20.4
17 B 21 26.7
18 B 24 33.9
19 B 27 42.0
20 B 30 51.0