R-从最后一个非零值开始按顺序填充na值



我有一个数据帧列,如下所示:

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分组然后获得NAs的行索引并不是真正优雅的;在其他解决方案(例如使用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
})

最新更新