首页 > 解决方案 > 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 循环,因为我的行数非常大。

谢谢。

标签: rdplyr

解决方案


一种选择:

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))]

推荐阅读