计算 data.frame 列中相邻的 NA

count adjacent NAs in data.frame column

我想添加一个额外的列 "na_count" 来计算列值中相邻的 NA,例如

value na_count
    8        0
    2        0 
   NA        4
   NA        4
   NA        4
   NA        4
    5        0
    9        0
    1        0
   NA        2
   NA        2 
    5        0
   NA        3
   NA        3
   NA        3
    8        0
    5        0
   NA        1

有没有办法使用 dplyr window 函数?

不使用 dplyr,而是使用来自 base-R 的 rle

# get run-length of missings
dd_rle <- rle(is.na(dd$value))

# use rep: value is length if missing, 0 otherwise, number of repetitions
# is length of runs
# na_count2 so comparison to expected output possible
dd$na_count2 <- rep(ifelse(dd_rle$values, dd_rle$lengths, 0),
                    dd_rle$lengths)

这是一个使用 dplyr 的选项(正如作者所要求的)。我们通过取逻辑向量 (!is.na(value)) 的差来创建分组列,与 1 进行比较并执行 cumsum,然后通过将逻辑向量与元素数相乘来创建 'NA_count'小组 (n()).

library(dplyr)
df1 %>% 
  select(-na_count) %>% #removing the column that was not needed
  group_by(grp=cumsum(c(TRUE,abs(diff(!is.na(value)))==1))) %>% 
  mutate(NA_count = is.na(value)*n()) %>%
  ungroup() %>%
  select(-grp)

或者我们可以将'data.frame'转换为'data.table'(setDT(df1)),按逻辑向量(is.na(value))的rleid分组,我们得到nrow (.N),乘以逻辑向量并提取 'V1' 列。

library(data.table)#v1.9.6+
setDT(df1)[, .N*is.na(value) ,rleid(is.na(value))]$V1
#[1] 0 0 4 4 4 4 0 0 0 2 2 0 3 3 3 0 0 1

如果这是创建一个新列,

setDT(df1)[, Na_count:= .N*is.na(value) ,rleid(is.na(value))]

或者我们可以使用 base R 中的 rle(运行 长度编码)。我们在 list 中得到 'value' 的 rle 是 NA (is.na(df1$value)),使用 within.list 改变 'values' 即 TRUE 元素,将其用作相应 'lengths' 的索引,然后 return 具有 inverse.rle.

的原子向量
inverse.rle(within.list(rle(is.na(df1$value)),
                {values[values] <- lengths[values] }))
#[1] 0 0 4 4 4 4 0 0 0 2 2 0 3 3 3 0 0 1

或者稍微紧凑一点的版本是

inverse.rle(within.list(rle(is.na(df1$value)), values <-lengths*values))
#[1] 0 0 4 4 4 4 0 0 0 2 2 0 3 3 3 0 0 1