如何用collapse/kit包替代R中dplyr的if_all和if_any函数
用collapse或kit包替代dplyr的
if_all和if_any实现高效数据处理 在处理大型数据集时,dplyr的if_all和if_any可能存在性能瓶颈,使用collapse或kit包的对应函数可以获得更快的处理速度。以下是正确的实现方式,先分析原代码的问题:
原代码中使用fsum(fselect(., A2, A3) %in% c(1, 2))时,fsum默认按列求和,而非按行计算每行满足条件的元素数量,因此得到的结果不符合预期。
一、使用collapse包实现
collapse包提供了专门的行级逻辑判断函数,完美对应dplyr的两个函数:
frowall(x, cond):判断每行所有元素是否满足条件(等效if_all)frowany(x, cond):判断每行任意元素是否满足条件(等效if_any)
正确代码
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 ) # 实现if_all和if_any的等效功能 df1 %>% fmutate( A4 = frowall(fselect(., A2, A3), \(x) x %in% c(1, 2)), A5 = frowany(fselect(., 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
该结果与dplyr的if_all/if_any输出完全一致。
如果坚持使用fsum的方式,需指定按行求和(MARGIN=1),代码如下:
df1 %>% fmutate( A4 = fsum(fselect(., A2, A3) %in% c(1, 2), MARGIN = 1) == 2, A5 = fsum(fselect(., A2, A3) %in% c(1, 2), MARGIN = 1) >= 1 )
同样可以得到正确结果,但frowall/frowany更直观且性能更优。
二、使用kit包实现
kit包提供了row_all和row_any函数,直接实现行级的全满足/任意满足判断:
正确代码
library(tidyverse) library(kit) df1 %>% mutate( A4 = row_all(fselect(., A2, A3) %in% c(1, 2)), A5 = row_any(fselect(., A2, A3) %in% c(1, 2)) )
输出结果
与dplyr、collapse的结果完全一致。
内容的提问来源于stack exchange,提问作者MYaseen208
相关产品推荐
相关产品推荐

