这是一个使用dplyr 的选项(正如作者所要求的)。我们通过取逻辑向量的差 (!is.na(value)) 创建一个分组列,与 1 进行比较并执行 cumsum,然后通过将逻辑向量乘以组中的元素数 (n()) 创建“NA_count” )。
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 更改'值',即TRUE 元素,将其用作相应'长度'的索引然后用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