如何使用or
在列表中以元素方式有效地组合逻辑向量,以便获得相同长度的向量?
我有一个列表选项,其中包含一组长度相同的逻辑向量。
> str(opts)
List of 7
$ option1: logi [1:608247] FALSE FALSE FALSE FALSE FALSE FALSE ...
$ option2: logi [1:608247] FALSE FALSE FALSE FALSE FALSE FALSE ...
$ option3: logi [1:608247] FALSE FALSE FALSE FALSE FALSE FALSE ...
$ option4: logi [1:608247] FALSE TRUE FALSE TRUE TRUE TRUE ...
$ option5: logi [1:608247] FALSE TRUE FALSE FALSE TRUE FALSE ...
$ option6: logi [1:608247] FALSE FALSE FALSE FALSE FALSE FALSE ...
$ option7: logi [1:608247] FALSE FALSE FALSE FALSE FALSE FALSE ...
我希望这样做:
logi [1:608247] FALSE TRUE FALSE TRUE TRUE TRUE ...
我可以将我的数据结构更改为matrix
或data.frame
或其他更好的东西,如果它更好,我只是从lapply
获取此内容。
答案 0 :(得分:26)
如何减少:
Reduce("&", opts)
Reduce("|", opts)
答案 1 :(得分:6)
如果所有列表的长度相同,则可以将其强制转换为数据框,然后使用any
:
apply(data.frame(opts),1,any)
编辑:虽然我认为这可能很快,因为它避免了cbind
,但事实证明,根据我的基准测试,这是迄今为止最慢的三种解决方案:
set.seed(123)
opts = as.list(as.data.frame(matrix(sample(c(TRUE, FALSE), 10000, replace=TRUE), nrow=1000)))
require(microbenchmark)
microbenchmark(Reduce("|",opts),rowSums(do.call(cbind, opts)) > 0,
apply(as.data.frame(opts),1,any))
Unit: microseconds
expr min lq median uq
Reduce("|", opts) 99.200 101.0780 106.596 110.3725
rowSums(do.call(cbind, opts)) > 0 209.326 211.9665 217.329 224.0505
apply(as.data.frame(opts), 1, any) 4130.429 4245.7380 4308.054 4438.2485
max neval
120.63 100
237.19 100
6949.19 100
答案 2 :(得分:3)
你可以这样做:
(rowSums(do.call(cbind, opts)) > 0)
例如:
opts = as.list(as.data.frame(matrix(sample(c(TRUE, FALSE), 10000, replace=TRUE), nrow=1000)))
str(opts)
do.call(cbind, opts)
创建一个1000x10的TRUE和FALSE矩阵:
dim(do.call(cbind, opts))
# [1] 1000 10
head(do.call(cbind, opts))
# V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
#[1,] TRUE TRUE FALSE FALSE TRUE TRUE FALSE TRUE TRUE FALSE
#[2,] FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE
#[3,] FALSE TRUE TRUE FALSE TRUE FALSE FALSE FALSE TRUE TRUE
#[4,] FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE TRUE TRUE
#[5,] FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE TRUE FALSE
#[6,] FALSE FALSE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE
rowSums
将创建一个向量,显示每行中的TRUE值的数量:在该行总和大于0的任何情况下,逻辑或返回TRUE。
答案 3 :(得分:0)
使用 pmap() 和 any() 的解决方案,以及一些额外的基准测试
我也喜欢使用 purrr
的 pmap
,作为行操作的一般方法。
pmap 绝对不是最快的,如下面的基准测试所示(未矢量化为 Reduce() 或 reduce() 或 rowSums()),但我发现它非常通用且一致。
在这种情况下,您可以将它与 any
一起使用,这比嵌套/顺序 |
更快,对我来说更直观。
library(purrr)
opts%>%pmap_lgl(., any)
purrr
的 Reduce()
版本 reduce()
与 @Ricardo Saporta 的回答类似,但保持了我们在 purrr 中看到的语法的一致性:
library(purrr)
opts%>%reduce(., `|`)
我也做了一些基准测试。
microbenchmark(Reduce("|",opts),
Reduce(any, opts),
rowSums(do.call(cbind, opts)) > 0,
apply(as.data.frame(opts),1,any),
pmap_lgl(opts, any),
reduce(opts, any),
reduce(opts, `|`)
)
Unit: microseconds
expr min lq mean median uq max neval
Reduce("|", opts) 40.303 59.3935 87.71092 77.5005 107.3490 461.228 100
Reduce(any, opts) 8.576 15.6625 29.48404 23.6775 31.9965 185.628 100
rowSums(do.call(cbind, opts)) > 0 70.458 94.8565 133.39620 130.3765 154.3775 675.701 100
apply(as.data.frame(opts), 1, any) 2580.162 3642.5935 4848.82291 4725.7095 5476.0935 19805.711 100
pmap_lgl(opts, any) 7420.634 11071.3780 14972.01035 13362.0735 14820.2190 164536.018 100
reduce(opts, any) 229.924 388.0765 515.31035 524.9820 629.1945 1052.248 100
reduce(opts, `|`) 277.262 485.9855 688.35137 699.9830 790.6440 1717.872 100
基准测试清楚地表明 Reduce() 是最快的 Reduce>rowSums+cbind>reduce>apply>pmap_lgl
并且 any>"|"