R 中数据操作的 if_all 和 if_any 的替代方案

问题描述 投票:0回答:1

我一直在使用

if_all
包中的
if_any
dplyr
函数在 R 中进行数据操作。但是,我注意到这些函数在处理大型数据集时可能会非常慢。因此,我正在寻找
collapse
kit
R 包中可用的替代方案。

当我尝试使用

collapse
包时,我没有获得预期的结果。下面是我的 R 代码的输出,它说明了我遇到的差异:

library(tidyverse)
library(collapse)

set.seed(12345)
df1 <-
  data.frame(
    A1 = runif(n = 10, min = 1, max = 3) %>% round
  , A2 = runif(n = 10, min = 1, max = 4) %>% round
  , A3 = runif(n = 10, min = 1, max = 5) %>% round
  )

df1
#>    A1 A2 A3
#> 1   2  1  3
#> 2   3  1  2
#> 3   3  3  5
#> 4   3  1  4
#> 5   2  2  4
#> 6   1  2  3
#> 7   2  2  4
#> 8   2  2  3
#> 9   2  2  2
#> 10  3  4  3

df1 %>% 
  mutate(
    A4 = if_all(c(A2, A3), \(x) x %in% c(1, 2))
  , A5 = if_any(c(A2, A3), \(x) x %in% c(1, 2))
    )
#>    A1 A2 A3    A4    A5
#> 1   2  1  3 FALSE  TRUE
#> 2   3  1  2  TRUE  TRUE
#> 3   3  3  5 FALSE FALSE
#> 4   3  1  4 FALSE  TRUE
#> 5   2  2  4 FALSE  TRUE
#> 6   1  2  3 FALSE  TRUE
#> 7   2  2  4 FALSE  TRUE
#> 8   2  2  3 FALSE  TRUE
#> 9   2  2  2  TRUE  TRUE
#> 10  3  4  3 FALSE FALSE
  
df1 %>% 
  fmutate(
    A4 = fsum(fselect(., A2, A3) %in% c(1, 2)) == 2
  , A5 = fsum(fselect(., A2, A3) %in% c(1, 2)) >= 1
    )
#>    A1 A2 A3    A4    A5
#> 1   2  1  3 FALSE FALSE
#> 2   3  1  2 FALSE FALSE
#> 3   3  3  5 FALSE FALSE
#> 4   3  1  4 FALSE FALSE
#> 5   2  2  4 FALSE FALSE
#> 6   1  2  3 FALSE FALSE
#> 7   2  2  4 FALSE FALSE
#> 8   2  2  3 FALSE FALSE
#> 9   2  2  2 FALSE FALSE
#> 10  3  4  3 FALSE FALSE

您能否建议如何使用

if_all
if_any
包正确实现
collapse
kit
的替代方案?任何见解或例子将不胜感激。

r dplyr tidyverse r-collapse kit
1个回答
5
投票

你没有说你是否也在使用

collapse
版本的
%in%
,但如果没有,我会从那里开始。

请参阅

fmatch
的帮助页面,其中建议通过运行
 设置 
%in%
 以使用基于 
fmatch

的更快版本
set_collapse(mask = "%in%")

然后我会尝试再次运行您的初始代码。当我使用 1e7 行的初始数据大小执行此操作时,运行时间从 1.6 秒下降到 0.6 秒。

我认为布尔运算符也可能更快,但是当我比较此代码时,它实际上比初始代码慢。

df1 %>% 
  mutate(
    A4 = (A2==1 | A2==2) & (A3==1 | A3==2),
    A5 = (A2==1 | A2==2) | (A3==1 | A3==2)
  )
© www.soinside.com 2019 - 2024. All rights reserved.