计算 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
我想添加一个额外的列 "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