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

R语言中基于条件对指定列前3个非零值求和的优化实现问询

简洁实现R语言分组后取前3个非零历史值求和与计数

你要按a1分组、event_id降序排列后,对var1_stat和var2_stat的前3个非零历史值求和并统计数量,当前逐个定义滞后变量的写法太繁琐,下面给你两种更简洁的实现方式:

方案1:用dplyr+purrr(无需额外安装包)

library(dplyr)
library(purrr)

# 原始数据
a1 <- c('adam', 'adam', 'adam', 'adam', 'megan', 'megan', 'megan','jen', 'jen', 'jen', 'jen')
event_id <- as.numeric(c('1', '2', '3', '6', '2', '4', '5', '1', '2', '4', '6'))
var1_stat <- as.numeric(c('3.2', '2.1', '2.7', '0','2','3.3', '1.1', '0', '4.1', '2.2','3.1'))
var2_stat <- as.numeric(c('3.4', '3', '0','1.7', '1.2', '3', '0','3.3', '2.1', '3.2', '0'))
test_ex <- data.frame(a1, event_id, var1_stat, var2_stat)

# 简洁实现
result <- test_ex %>%
  group_by(a1) %>%
  arrange(event_id, .by_group = TRUE) %>% # 先按event_id升序,让历史值排在当前行前面
  mutate(
    # 处理var1:收集所有历史非零值,取前3个求和、计数
    var1_sum3 = map_dbl(accumulate(var1_stat, ~c(.x, .y), .init = numeric(0)), 
                        ~sum(tail(.x, -1)[tail(.x, -1) != 0][1:3], na.rm = TRUE)),
    var1_count3 = map_dbl(accumulate(var1_stat, ~c(.x, .y), .init = numeric(0)), 
                          ~length(tail(.x, -1)[tail(.x, -1) != 0][1:3])),
    # 处理var2
    var2_sum3 = map_dbl(accumulate(var2_stat, ~c(.x, .y), .init = numeric(0)), 
                        ~sum(tail(.x, -1)[tail(.x, -1) != 0][1:3], na.rm = TRUE)),
    var2_count3 = map_dbl(accumulate(var2_stat, ~c(.x, .y), .init = numeric(0)), 
                          ~length(tail(.x, -1)[tail(.x, -1) != 0][1:3]))
  ) %>%
  arrange(desc(event_id), .by_group = TRUE) %>% # 还原成event_id降序
  ungroup()

print(result)

方案2:用slider包(滑动窗口更直观)

如果习惯用滑动窗口逻辑,可以用slider包,代码更易懂:

library(dplyr)
library(slider)

result <- test_ex %>%
  group_by(a1) %>%
  arrange(event_id, .by_group = TRUE) %>%
  mutate(
    # .before = Inf 表示取当前行之前的所有历史数据
    var1_sum3 = slide_dbl(var1_stat, 
                          ~sum(.[. != 0][1:3], na.rm = TRUE), 
                          .before = Inf, .complete = FALSE),
    var1_count3 = slide_dbl(var1_stat, 
                            ~length(.[. != 0][1:3]), 
                            .before = Inf, .complete = FALSE),
    var2_sum3 = slide_dbl(var2_stat, 
                          ~sum(.[. != 0][1:3], na.rm = TRUE), 
                          .before = Inf, .complete = FALSE),
    var2_count3 = slide_dbl(var2_stat, 
                            ~length(.[. != 0][1:3]), 
                            .before = Inf, .complete = FALSE)
  ) %>%
  arrange(desc(event_id), .by_group = TRUE) %>%
  ungroup()

print(result)

关键说明

  • 两种方案都先按a1分组,再升序排列event_id,保证当前行的所有历史值(event_id更小的)都在上方,处理完再还原降序,完全符合你的需求。
  • 如果要取最近的3个非零历史值(而不是最早的3个),把代码里的[1:3]改成tail(., 3)就行。
  • 不用手动定义一堆滞后变量,要改取前N个值的话,直接改数字就行,扩展性拉满。

内容的提问来源于stack exchange,提问作者DonnyDolio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 11:21:03