如何在apply函数中使用if语句?R语言循环计数代码优化求助
优化方案:用分组聚合替代循环/Apply
你的需求本质是按a和b分组,统计每组中c值≥0(positive)和<0(negative)的数量,完全不需要用循环或者逐行的apply——这俩都是低效的逐行操作,大数据量下肯定卡。下面给你三种高效的实现方式,优先级从高到低:
1. 最快最优:用data.table(适合超大规模数据)
data.table是R中处理大数据的神器,底层用C实现,速度和内存效率都拉满,260k行数据秒出结果:
# 加载包(如果没装先运行 install.packages("data.table")) library(data.table) # 把你的原始数据转成data.table格式 dt <- as.data.table(df1) # 分组统计一行搞定 dfOcc <- dt[, .( positive = sum(c >= 0), negative = sum(c < 0) ), by = .(a, b)] # 按a和b分组 # 查看结果 print(dfOcc)
2. 语法更直观:用dplyr(tidyverse生态,易读易维护)
如果你习惯tidyverse的语法,dplyr的分组聚合同样高效,代码可读性更强:
# 加载包(没装先运行 install.packages("dplyr")) library(dplyr) dfOcc <- df1 %>% group_by(a, b) %>% # 按a和b分组 summarize( positive = sum(c >= 0), # 统计每组c≥0的数量 negative = sum(c < 0), # 统计每组c<0的数量 .groups = "drop" # 取消分组,返回普通数据框 ) print(dfOcc)
3. 原生base R实现(无需额外包)
如果不想装包,用base R的aggregate也能搞定,虽然速度比上面两个慢一些,但比你的循环快N倍:
# 分组聚合 agg_result <- aggregate(c ~ a + b, data = df1, FUN = function(x) { c(positive = sum(x >= 0), negative = sum(x < 0)) }) # 把嵌套的结果展开成普通数据框 dfOcc <- do.call(data.frame, agg_result) colnames(dfOcc) <- c("a", "b", "positive", "negative") print(dfOcc)
为什么你的原代码这么慢?
你原来的循环犯了两个致命的效率问题:
- 逐行查找匹配:每次循环都用
which(dfOcc$a==x && dfOcc$b==y)去检索行,这是线性查找,260k次循环就意味着260k×10k=2.6e9次操作,完全是灾难级的时间复杂度。 - 频繁修改数据框:每次循环都修改
dfOcc的单元格,R的数据框是列存储,频繁修改会不断复制内存,进一步拖慢速度。
而上面的分组聚合方法都是向量化操作,只需要遍历原始数据一次,按组统计,时间复杂度是O(n),效率提升几个数量级。
内容的提问来源于stack exchange,提问作者Axel
相关产品推荐
相关产品推荐

