我有一个数据框列,如下所示:
a
<int>
1 11127
2 0
3 0
4 NA
5 0
6 0
7 NA
8 0
9 11580
11 0
12 NA
13 0
我想从最后一个非零值开始顺序填充NA值,以便最终结果如下所示:
a
<int>
1 11127
2 0
3 0
4 11128
5 0
6 0
7 11129
8 0
9 11580
11 0
12 11581
13 0
是否有dplyr
(最好)或基于R的方法?我宁愿避免for循环,因为行数很大。
谢谢。
答案 0 :(得分:6)
一个选项:
library(dplyr)
df %>%
group_by(idx = cumsum(!(is.na(a) | a == 0)), is.na(a)) %>%
mutate(rn = row_number()) %>%
group_by(idx) %>%
mutate(a = coalesce(a, first(a) + rn)) %>%
ungroup() %>%
select(a)
输出:
# A tibble: 12 x 1
a
<int>
1 11127
2 0
3 0
4 11128
5 0
6 0
7 11129
8 0
9 11580
10 0
11 11581
12 0
如果速度是一个问题,那么等效的data.table
可能会稍微快一些:
library(data.table)
setDT(df)[, rn := rowid(a), .(cumsum(!(is.na(a) | a == 0)), is.na(a))][
, a := fcoalesce(a, first(a) + rn), by = cumsum(!(is.na(a) | a == 0))][
, rn := NULL]
编辑
将IMO分组然后获取NA
的行索引并不是很完美;最好在其他解决方案中看到(例如,使用cumsum
)。
使用fcoalesce
,然后可以在单个data.table
步骤中解决问题:
library(data.table)
setDT(df)[, a := fcoalesce(a, first(a) + cumsum(is.na(a))), by = cumsum(!(is.na(a) | a == 0))]
答案 1 :(得分:5)
使用dplyr
的一种解决方案可能是:
df %>%
group_by(id = cumsum(!is.na(a) & a != 0)) %>%
mutate(a = ifelse(is.na(a), first(a) + cumsum(is.na(a)), a))
a id
<int> <int>
1 11127 1
2 0 1
3 0 1
4 11128 1
5 0 1
6 0 1
7 11129 1
8 0 1
9 11580 2
10 0 2
11 11581 2
12 0 2
答案 2 :(得分:4)
使用cumsum(logical)
和ave
的基本R方法。
nze <- df1$a != 0 & !is.na(df1$a)
ave(df1$a, cumsum(nze), FUN = function(x){
na <- is.na(x)
x[na] <- x[!na][1] + seq_along(which(na))
x
})
# [1] 11127 0 0 11128 0 0 11129 0 11580 0 11581 0
然后分配此结果。
df1$a <- ave(df1$a, cumsum(nze), FUN = function(x){
na <- is.na(x)
x[na] <- x[!na][1] + seq_along(which(na))
x
})