tidyverse/data.table中实现分组累积自定义函数计算
没问题!我帮你用tidyverse和data.table两种主流框架来实现这个累积分组计算的需求,完全不用循环~
使用tidyverse框架实现
在tidyverse生态中,我们可以结合dplyr的分组功能和purrr的accumulate()函数来完成累积计算。accumulate()会逐个迭代目标向量,每次将当前值与之前的累积集合合并后传入自定义函数。
首先我们先定义一个示例的myfun(这里用标准差做演示,你可以替换成自己的函数):
myfun <- function(x) sd(x, na.rm = TRUE)
然后处理你的数据集:
library(tidyverse) # 初始化数据 a <- tibble(id = rep(c("A", "B"), each = 6), val = c(1, 0, 0, 1 ,0,1,0,0,0,1,1,1)) # 分组计算累积结果 a_result <- a %>% group_by(id) %>% mutate( result = accumulate( val, ~ myfun(c(.x, .y)), # 每次合并之前的累积集合和当前值,传入myfun .init = numeric(0) # 初始值设为空向量,确保第一次计算包含第一个val ) %>% tail(-1) # 去掉.init对应的初始空结果,匹配原数据行数 ) %>% ungroup()
使用data.table框架实现
data.table可以通过Reduce()函数配合accumulate = TRUE参数来实现分组累积计算,这种方式更贴合data.table的原生风格:
library(data.table) # 初始化并转换为data.table格式 a <- tibble(id = rep(c("A", "B"), each = 6), val = c(1, 0, 0, 1 ,0,1,0,0,0,1,1,1)) setDT(a) # 定义自定义函数 myfun <- function(x) sd(x, na.rm = TRUE) # 分组计算累积结果 a[, result := Reduce( function(acc, curr) { new_acc <- c(acc, curr) myfun(new_acc) }, val, accumulate = TRUE ), by = id]
补充说明
- 如果你的
myfun在输入长度为1时需要特殊处理(比如单个值的标准差是NA,你可以改成返回0或其他值),只需要在myfun里加个判断即可,例如:
myfun <- function(x) { if (length(x) < 2) return(0) sd(x, na.rm = TRUE) }
- 两种方法都会保证每个
id分组内独立计算累积结果,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Cettt
相关产品推荐
相关产品推荐

