You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:13:46