识别向量中的 NA 集
Identify sets of NA in a vector
假设我有一个向量 x
:
x <- c(NA, NA, 1, 2, NA, NA, 3, 4)
如何识别此向量中的 NA 集,即
na_set <- c(1, 1, 0, 0, 2, 2, 0, 0)
我的最终目标是使用 dplyr
将其与数据框上的管道一起使用。所以,如果有兼容dplyr的功能就更好了。
谢谢!
你可以取is.na(x)
的diff
。这将是 1
IFF 元素是 TRUE
而前一个元素是 FALSE
。在应用 == 1
之后,您有一个逻辑向量,它是 TRUE
for NA
-group starts。然后你可以用 cumsum
来确定你在哪个 NA
组,然后乘以 is.na(x)
将非 NA
设置为 0
.
cumsum(diff(is.na(c(1, x))) == 1)*is.na(x)
#[1] 1 1 0 0 2 2 0 0
显示的中间结果:
a <- is.na(c(1, x))
a
#[1] FALSE TRUE TRUE FALSE FALSE TRUE TRUE FALSE FALSE
b <- diff(a) == 1
b
#[1] TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE
d <- cumsum(b)
d
#[1] 1 1 1 1 2 2 2 2
我很感兴趣,所以我做了一个基准测试。我认为结果实际上并不重要,即使 length(x)
of 1e7
.
的差异也以毫秒为单位
x <- c(NA,NA, 1,2,NA,NA, 3,4)
x <- sample(x, 1e7, T)
f_rleid <- function(x){
nax <- is.na(x)
r <- rleid(x)*nax
r[nax] <- rleid(r[nax])
r
}
f_rle <- function(x){
r <- rle(is.na(x))
r$values <- cumsum(r$values) * r$values
inverse.rle(r)
}
f_diffna <- function(x){
nax <- is.na(x)
cumsum(c(as.integer(nax[1]), diff(nax)) == 1L)*nax
}
all.equal(f_rleid(x), f_rle(x))
# [1] TRUE
all.equal(f_rleid(x), f_diffna(x))
# [1] TRUE
microbenchmark::microbenchmark(f_rleid(x), f_rle(x),f_diffna(x))
# Unit: milliseconds
# expr min lq mean median uq max neval
# f_rleid(x) 421.9483 437.3314 469.3564 446.5081 511.9315 582.5812 100
# f_rle(x) 451.3790 519.5278 560.8057 572.4148 591.7632 697.2100 100
# f_diffna(x) 248.3631 267.5462 315.6224 291.5910 362.8829 459.6873 100
计算 is.na(x) 的 运行 长度编码,并用序列号或 0 替换值。然后反转回来。
r <- rle(is.na(x))
r$values <- cumsum(r$values) * r$values
inverse.rle(r)
## [1] 1 1 0 0 2 2 0 0
如果集合的确切排名不是问题,您可以使用 data.table
:
中方便的 rleid()
函数
rleid(x) * is.na(x)
[1] 1 1 0 0 4 4 0 0
速度对比:
library(microbenchmark)
x <- rep(x, 1e5)
microbenchmark(
IceCreamToucan = cumsum(diff(is.na(c(1, x))) == 1)*is.na(x),
tmfmnk = rleid(x) * is.na(x),
G._Grothendieck = {r <- rle(is.na(x))
r$values <- cumsum(r$values) * r$values
inverse.rle(r)},
times = 5
)
Unit: milliseconds
expr min lq mean median uq max neval cld
IceCreamToucan 48.607317 52.49508 66.64196 74.63182 76.81896 80.65662 5 b
tmfmnk 9.952486 12.58168 20.22834 14.38625 16.23961 47.98166 5 a
G._Grothendieck 53.533149 57.48818 59.12514 59.73295 62.14772 62.72371 5 b
假设我有一个向量 x
:
x <- c(NA, NA, 1, 2, NA, NA, 3, 4)
如何识别此向量中的 NA 集,即
na_set <- c(1, 1, 0, 0, 2, 2, 0, 0)
我的最终目标是使用 dplyr
将其与数据框上的管道一起使用。所以,如果有兼容dplyr的功能就更好了。
谢谢!
你可以取is.na(x)
的diff
。这将是 1
IFF 元素是 TRUE
而前一个元素是 FALSE
。在应用 == 1
之后,您有一个逻辑向量,它是 TRUE
for NA
-group starts。然后你可以用 cumsum
来确定你在哪个 NA
组,然后乘以 is.na(x)
将非 NA
设置为 0
.
cumsum(diff(is.na(c(1, x))) == 1)*is.na(x)
#[1] 1 1 0 0 2 2 0 0
显示的中间结果:
a <- is.na(c(1, x))
a
#[1] FALSE TRUE TRUE FALSE FALSE TRUE TRUE FALSE FALSE
b <- diff(a) == 1
b
#[1] TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE
d <- cumsum(b)
d
#[1] 1 1 1 1 2 2 2 2
我很感兴趣,所以我做了一个基准测试。我认为结果实际上并不重要,即使 length(x)
of 1e7
.
x <- c(NA,NA, 1,2,NA,NA, 3,4)
x <- sample(x, 1e7, T)
f_rleid <- function(x){
nax <- is.na(x)
r <- rleid(x)*nax
r[nax] <- rleid(r[nax])
r
}
f_rle <- function(x){
r <- rle(is.na(x))
r$values <- cumsum(r$values) * r$values
inverse.rle(r)
}
f_diffna <- function(x){
nax <- is.na(x)
cumsum(c(as.integer(nax[1]), diff(nax)) == 1L)*nax
}
all.equal(f_rleid(x), f_rle(x))
# [1] TRUE
all.equal(f_rleid(x), f_diffna(x))
# [1] TRUE
microbenchmark::microbenchmark(f_rleid(x), f_rle(x),f_diffna(x))
# Unit: milliseconds
# expr min lq mean median uq max neval
# f_rleid(x) 421.9483 437.3314 469.3564 446.5081 511.9315 582.5812 100
# f_rle(x) 451.3790 519.5278 560.8057 572.4148 591.7632 697.2100 100
# f_diffna(x) 248.3631 267.5462 315.6224 291.5910 362.8829 459.6873 100
计算 is.na(x) 的 运行 长度编码,并用序列号或 0 替换值。然后反转回来。
r <- rle(is.na(x))
r$values <- cumsum(r$values) * r$values
inverse.rle(r)
## [1] 1 1 0 0 2 2 0 0
如果集合的确切排名不是问题,您可以使用 data.table
:
rleid()
函数
rleid(x) * is.na(x)
[1] 1 1 0 0 4 4 0 0
速度对比:
library(microbenchmark)
x <- rep(x, 1e5)
microbenchmark(
IceCreamToucan = cumsum(diff(is.na(c(1, x))) == 1)*is.na(x),
tmfmnk = rleid(x) * is.na(x),
G._Grothendieck = {r <- rle(is.na(x))
r$values <- cumsum(r$values) * r$values
inverse.rle(r)},
times = 5
)
Unit: milliseconds
expr min lq mean median uq max neval cld
IceCreamToucan 48.607317 52.49508 66.64196 74.63182 76.81896 80.65662 5 b
tmfmnk 9.952486 12.58168 20.22834 14.38625 16.23961 47.98166 5 a
G._Grothendieck 53.533149 57.48818 59.12514 59.73295 62.14772 62.72371 5 b