使用最后一个值的 r 中的子集
subset in r using last value
我有一个像
这样的数据集
x <- c(FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE)
并且我希望所有最终值为真的子集,例如:
FALSE FALSE FALSE TRUE
FALSE FALSE TRUE
FALSE FALSE FALSE TRUE
FALSE TRUE
我尝试使用循环并尝试获得高于 TRUE
的 5 个值,但由于不对称,我没有得到想要的结果。我已经复制了这个例子,其中原始的有更多的差异。任何解决方案将不胜感激。
只用两行代码就可以达到你想要的效果:
splitAt <- function(x, pos) unname(split(x, cumsum(seq_along(x) %in% pos)))
> splitAt(x, which(x)+1)
[[1]]
[1] "FALSE" "FALSE" "FALSE" "TRUE"
[[2]]
[1] "FALSE" "FALSE" "TRUE"
[[3]]
[1] "FALSE" "FALSE" "FALSE" "TRUE"
[[4]]
[1] "FALSE" "TRUE"
数据:
x <- c("FALSE", "FALSE", "FALSE", "TRUE",
"FALSE", "FALSE", "TRUE",
"FALSE", "FALSE", "FALSE", "TRUE",
"FALSE", "TRUE")
我感谢this great SO answer,它想到了我上面使用的非常有用的功能splitAt()
。
这可以通过简单的 lapply
一行完成
lapply(diff(c(0, which(x))), function(x) c(rep(FALSE, (x-1)), TRUE))
#[[1]]
#[1] FALSE FALSE FALSE TRUE
#[[2]]
#[1] FALSE FALSE TRUE
#[[3]]
#[1] FALSE FALSE FALSE TRUE
#[[4]]
#[1] FALSE TRUE
说明
which(x)
给我们 TRUE
值的位置 (4, 7, 11, 13
)
- 从0开始,我们想要每个TRUE之间的差值(本质上就是
FALSE
的计数)- diff(c(0, which(x)))
- 4 3 4 2
- 对于这些值中的每一个,我们都需要一个
length(x)
的向量,具有 x - 1
FALSE
个值,并且 1
TRUE
- c(rep(FALSE, (x-1)), TRUE)
lapply
对每个 4 3 4 2
值执行此操作,returns 列表
基准测试
比较解决方案
library(microbenchmark)
splitAt <- function(x, pos) unname(split(x, cumsum(seq_along(x) %in% pos)))
microbenchmark(
splitAt(x, which(x)+1),
{r <- rle(x)$lengths
lapply(r[seq(1,length(r), by=2)] , function(x) c(rep(FALSE, x), TRUE))},
split(x, sum(x) - rev(cumsum(rev(x))) ),
trimws(strsplit(paste(x, collapse=" "), "(?<=TRUE)", perl=T)[[1]]),
lapply(diff(c(0, which(x))), function(x) c(rep(FALSE, (x-1)), TRUE))
)
# min lq mean median uq max neval
# 83.827 86.3910 91.76449 88.9155 92.8350 155.722 100
# 94.373 97.6275 105.10872 101.1455 105.8545 307.927 100
# 85.532 88.0660 93.59524 91.7935 95.3715 126.419 100
#145.233 147.8755 152.65975 150.3250 156.5910 177.807 100
# 26.451 29.6130 31.81785 31.0470 33.1895 43.267 100
数据
x <- c(F, F, F, T, F , F, T, F, F, F, T, F, T)
我有一个像
这样的数据集 x <- c(FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE)
并且我希望所有最终值为真的子集,例如:
FALSE FALSE FALSE TRUE
FALSE FALSE TRUE
FALSE FALSE FALSE TRUE
FALSE TRUE
我尝试使用循环并尝试获得高于 TRUE
的 5 个值,但由于不对称,我没有得到想要的结果。我已经复制了这个例子,其中原始的有更多的差异。任何解决方案将不胜感激。
只用两行代码就可以达到你想要的效果:
splitAt <- function(x, pos) unname(split(x, cumsum(seq_along(x) %in% pos)))
> splitAt(x, which(x)+1)
[[1]]
[1] "FALSE" "FALSE" "FALSE" "TRUE"
[[2]]
[1] "FALSE" "FALSE" "TRUE"
[[3]]
[1] "FALSE" "FALSE" "FALSE" "TRUE"
[[4]]
[1] "FALSE" "TRUE"
数据:
x <- c("FALSE", "FALSE", "FALSE", "TRUE",
"FALSE", "FALSE", "TRUE",
"FALSE", "FALSE", "FALSE", "TRUE",
"FALSE", "TRUE")
我感谢this great SO answer,它想到了我上面使用的非常有用的功能splitAt()
。
这可以通过简单的 lapply
一行完成
lapply(diff(c(0, which(x))), function(x) c(rep(FALSE, (x-1)), TRUE))
#[[1]]
#[1] FALSE FALSE FALSE TRUE
#[[2]]
#[1] FALSE FALSE TRUE
#[[3]]
#[1] FALSE FALSE FALSE TRUE
#[[4]]
#[1] FALSE TRUE
说明
which(x)
给我们TRUE
值的位置 (4, 7, 11, 13
)- 从0开始,我们想要每个TRUE之间的差值(本质上就是
FALSE
的计数)-diff(c(0, which(x)))
-4 3 4 2
- 对于这些值中的每一个,我们都需要一个
length(x)
的向量,具有x - 1
FALSE
个值,并且1
TRUE
-c(rep(FALSE, (x-1)), TRUE)
lapply
对每个4 3 4 2
值执行此操作,returns 列表
基准测试
比较解决方案
library(microbenchmark)
splitAt <- function(x, pos) unname(split(x, cumsum(seq_along(x) %in% pos)))
microbenchmark(
splitAt(x, which(x)+1),
{r <- rle(x)$lengths
lapply(r[seq(1,length(r), by=2)] , function(x) c(rep(FALSE, x), TRUE))},
split(x, sum(x) - rev(cumsum(rev(x))) ),
trimws(strsplit(paste(x, collapse=" "), "(?<=TRUE)", perl=T)[[1]]),
lapply(diff(c(0, which(x))), function(x) c(rep(FALSE, (x-1)), TRUE))
)
# min lq mean median uq max neval
# 83.827 86.3910 91.76449 88.9155 92.8350 155.722 100
# 94.373 97.6275 105.10872 101.1455 105.8545 307.927 100
# 85.532 88.0660 93.59524 91.7935 95.3715 126.419 100
#145.233 147.8755 152.65975 150.3250 156.5910 177.807 100
# 26.451 29.6130 31.81785 31.0470 33.1895 43.267 100
数据
x <- c(F, F, F, T, F , F, T, F, F, F, T, F, T)