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

如何用dplyr在多条件下计算DataFrame列的滚动最大值或最小值?

问题

我正尝试使用dplyr,按多条件以「滚动方式」计算DataFrame某列每行的最大值。这里的「滚动方式」指计算范围从顶部(第1行)锚定,延伸至当前计算行(而非数组底部)。下方是可复现代码生成的DataFrame,我需要用dplyr重现对应Excel逻辑的目标值。

可复现代码:

library(dplyr)

myDF <- 
  data.frame(
    Names = c("R","R","B","R","X","X"),
    Group = c(0,1,1,2,2,0),
    Code1 = c(1,3,8,2,4,5)
  )

我的尝试代码(曾实现浮动数组版sumifs,但无法实现maxifs/minifs):

myDF %>% mutate(maxIfs = sapply(1:n(), function(x) max(Code1[1:x][(Names[1:x] == Names[x]) & (Group[1:x] == Group[x])])))

编辑后的代码(修正部分问题):

myDF %>% mutate(maxIfs = sapply(1:n(), function(x) max(Code1[1:x][(Names[1:x] == Names[x]) & (Group[1:x] == 0)], 0)))
解决方案

方法1:优化sapply实现

你的编辑后代码已经接近目标,这里优化空值处理逻辑,避免无匹配时返回-Inf:

myDF %>% 
  mutate(maxIfs = sapply(1:n(), function(x) {
    # 筛选第1行到当前行中,Names匹配且Group为0的Code1值
    filtered_vals <- Code1[1:x][Names[1:x] == Names[x] & Group[1:x] == 0]
    # 无匹配值返回0,否则返回最大值
    if (length(filtered_vals) == 0) 0 else max(filtered_vals)
  }))

方法2:tidyverse风格实现(用purrr替代sapply)

用purrr::map_dbl让代码更符合tidyverse的可读性要求:

library(purrr)

myDF %>% 
  mutate(maxIfs = map_dbl(row_number(), ~{
    # 取当前行及之前的所有行
    current_slice <- slice(., 1:.x)
    # 筛选符合条件的行
    matched_rows <- filter(current_slice, Names == Names[.x], Group == 0)
    # 计算最大值或返回0
    if (nrow(matched_rows) == 0) 0 else max(matched_rows$Code1)
  }))

方法3:高效分组累积计算(适合大数据集)

如果数据集较大,逐行处理效率偏低,可以按Names分组后用累积逻辑计算:

myDF %>%
  group_by(Names) %>%
  mutate(
    # 标记当前行是否满足Group==0条件
    is_valid = Group == 0,
    # 累积收集符合条件的Code1值
    cumulative_codes = accumulate(is_valid, ~if (.y) c(.x, Code1[cur_row()]) else .x),
    # 计算每个累积列表的最大值,空列表返回0
    maxIfs = map_dbl(cumulative_codes, ~if (length(.x) == 0) 0 else max(.x))
  ) %>%
  ungroup() %>%
  select(-is_valid, -cumulative_codes) # 移除中间辅助列

内容的提问来源于stack exchange,提问作者Village.Idyot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 20:40:48