如何删除 r 中带有 NA 的尾巴?
How to remove a tail with NA in r?
我有一个向量:
a <- c(NA,1:5,NA,NA,1:3, rep(NA,round(runif(1,0,100))))
我需要删除结尾的 NA
。期望的结果:
c(NA, 1:5, NA, NA, 1:3)
一个选项是
a[rev(cumprod(rev(is.na(a)))) == 0]
# [1] NA 1 2 3 4 5 NA NA 1 2 3
步骤如下:
(a <- c(NA, 1:5, NA, NA, 1:3, NA, NA))
# [1] NA 1 2 3 4 5 NA NA 1 2 3 NA NA
is.na(a)
# [1] TRUE FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE TRUE TRUE
rev(is.na(a))
# [1] TRUE TRUE FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE TRUE
cumprod(rev(is.na(a)))
# [1] 1 1 0 0 0 0 0 0 0 0 0 0 0
rev(cumprod(rev(is.na(a))))
# [1] 0 0 0 0 0 0 0 0 0 0 0 1 1
我认为这可行:
rm_NA_tail <- function(a) {
if (is.na(a[length(a)])) {
return(a[is.na(match(data.table::rleid(a), max(data.table::rleid(a))))])
} else {
return(a)
}
}
你可以做到
a[1:max(which(!is.na(a)))]
# [1] NA 1 2 3 4 5 NA NA 1 2 3
我们从位置 1 到最后一个非 NA 值对向量进行子集化。
你可以找到非 NA 的最大位置并相应地子集
> a[1:max(which(!is.na(a)))]
[1] NA 1 2 3 4 5 NA NA 1 2 3
还有一种可能性:
a[cumsum(!is.na(a)) != max(cumsum(!is.na(a))) * is.na(a)]
[1] NA 1 2 3 4 5 NA NA 1 2 3
在各个步骤中:
is.na(a)
[1] TRUE FALSE FALSE FALSE FALSE
cumsum(!is.na(a))
[1] 0 1 2 3 4
cumsum(!is.na(a)) != max(cumsum(!is.na(a)))
[1] TRUE TRUE TRUE TRUE TRUE
cumsum(!is.na(a)) != max(cumsum(!is.na(a))) * is.na(a)
[1] TRUE TRUE TRUE TRUE TRUE
纯属娱乐,一些基准测试:
library(microbenchmark)
a <- rep(a, 1e5)
microbenchmark(
markus = a[1:max(which(!is.na(a)))],
Julius_Vainora = a[rev(cumprod(rev(is.na(a)))) == 0],
Kim = rm_NA_tail(a),
tmfmnk = a[cumsum(!is.na(a)) != max(cumsum(!is.na(a))) * is.na(a)],
nsinghs = a[1:(length(a) - rle(is.na(rev(a)))$lengths[1])],
times = 5
)
Unit: milliseconds
expr min lq mean median uq max neval cld
markus 150.7346 153.0674 156.4194 153.3031 159.4718 165.5201 5 a
Julius_Vainora 393.8520 418.8186 616.3269 703.4022 749.6600 815.9018 5 bc
Kim 370.7680 382.1826 536.0828 632.0031 642.1882 653.2720 5 bc
tmfmnk 390.2626 415.2378 466.4245 415.8310 423.3828 687.4082 5 b
nsinghs 537.0404 781.1403 798.6929 793.1027 842.6777 1039.5033 5 c
这可以使用 rle()
来完成
a[1:(length(a) - rle(is.na(rev(a)))$lengths[1])]
# [1] NA 1 2 3 4 5 NA NA 1 2 3
rle(is.na(rev(a)))$lengths[1]
获取向量中尾随 NA
的计数,然后从总向量中减去它 length
以获得要保留向量的索引。
我有一个向量:
a <- c(NA,1:5,NA,NA,1:3, rep(NA,round(runif(1,0,100))))
我需要删除结尾的 NA
。期望的结果:
c(NA, 1:5, NA, NA, 1:3)
一个选项是
a[rev(cumprod(rev(is.na(a)))) == 0]
# [1] NA 1 2 3 4 5 NA NA 1 2 3
步骤如下:
(a <- c(NA, 1:5, NA, NA, 1:3, NA, NA))
# [1] NA 1 2 3 4 5 NA NA 1 2 3 NA NA
is.na(a)
# [1] TRUE FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE TRUE TRUE
rev(is.na(a))
# [1] TRUE TRUE FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE TRUE
cumprod(rev(is.na(a)))
# [1] 1 1 0 0 0 0 0 0 0 0 0 0 0
rev(cumprod(rev(is.na(a))))
# [1] 0 0 0 0 0 0 0 0 0 0 0 1 1
我认为这可行:
rm_NA_tail <- function(a) {
if (is.na(a[length(a)])) {
return(a[is.na(match(data.table::rleid(a), max(data.table::rleid(a))))])
} else {
return(a)
}
}
你可以做到
a[1:max(which(!is.na(a)))]
# [1] NA 1 2 3 4 5 NA NA 1 2 3
我们从位置 1 到最后一个非 NA 值对向量进行子集化。
你可以找到非 NA 的最大位置并相应地子集
> a[1:max(which(!is.na(a)))]
[1] NA 1 2 3 4 5 NA NA 1 2 3
还有一种可能性:
a[cumsum(!is.na(a)) != max(cumsum(!is.na(a))) * is.na(a)]
[1] NA 1 2 3 4 5 NA NA 1 2 3
在各个步骤中:
is.na(a)
[1] TRUE FALSE FALSE FALSE FALSE
cumsum(!is.na(a))
[1] 0 1 2 3 4
cumsum(!is.na(a)) != max(cumsum(!is.na(a)))
[1] TRUE TRUE TRUE TRUE TRUE
cumsum(!is.na(a)) != max(cumsum(!is.na(a))) * is.na(a)
[1] TRUE TRUE TRUE TRUE TRUE
纯属娱乐,一些基准测试:
library(microbenchmark)
a <- rep(a, 1e5)
microbenchmark(
markus = a[1:max(which(!is.na(a)))],
Julius_Vainora = a[rev(cumprod(rev(is.na(a)))) == 0],
Kim = rm_NA_tail(a),
tmfmnk = a[cumsum(!is.na(a)) != max(cumsum(!is.na(a))) * is.na(a)],
nsinghs = a[1:(length(a) - rle(is.na(rev(a)))$lengths[1])],
times = 5
)
Unit: milliseconds
expr min lq mean median uq max neval cld
markus 150.7346 153.0674 156.4194 153.3031 159.4718 165.5201 5 a
Julius_Vainora 393.8520 418.8186 616.3269 703.4022 749.6600 815.9018 5 bc
Kim 370.7680 382.1826 536.0828 632.0031 642.1882 653.2720 5 bc
tmfmnk 390.2626 415.2378 466.4245 415.8310 423.3828 687.4082 5 b
nsinghs 537.0404 781.1403 798.6929 793.1027 842.6777 1039.5033 5 c
这可以使用 rle()
a[1:(length(a) - rle(is.na(rev(a)))$lengths[1])]
# [1] NA 1 2 3 4 5 NA NA 1 2 3
rle(is.na(rev(a)))$lengths[1]
获取向量中尾随 NA
的计数,然后从总向量中减去它 length
以获得要保留向量的索引。