我有一个数据帧列,如下所示:
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循环,因为我的行数相当大。
谢谢。
利用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
一个选项:
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
s的行索引并不是真正优雅的;在其他解决方案(例如使用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))]
使用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
})