如何在R中对数据框分组后用rollapply计算滚动最小值?
按分组滚动窗口求全局最小值
原始数据与需求
首先构造示例数据:
library(tidyverse) library(zoo) date = c(rep(as.Date("2022/1/1"),5),rep(as.Date("2022/1/12"),5)) a = seq(1,10,1) b = seq(-1,-10,-1) c = seq(10,-20,length.out=10) window=c(rep(2,5),rep(3,5)) A = tibble(date,a,b,c,window);A
数据内容:
| date | a | b | c | window |
|---|---|---|---|---|
| 2022-01-01 | 1 | -1 | 10 | 2 |
| 2022-01-01 | 2 | -2 | 6.667 | 2 |
| 2022-01-01 | 3 | -3 | 3.333 | 2 |
| 2022-01-01 | 4 | -4 | 0 | 2 |
| 2022-01-01 | 5 | -5 | -3.333 | 2 |
| 2022-01-12 | 6 | -6 | -6.667 | 3 |
| 2022-01-12 | 7 | -7 | -10 | 3 |
| 2022-01-12 | 8 | -8 | -13.33 | 3 |
| 2022-01-12 | 9 | -9 | -16.67 | 3 |
| 2022-01-12 | 10 | -10 | -20 | 3 |
需求:按date分组,对a、b、c列应用对应分组的window值作为滚动窗口宽度,计算每个滚动窗口内所有元素的最小值,最后汇总每组所有滚动最小值中的全局最小值,得到如下结果:
| date | MINS |
|---|---|
| 2022-01-01 | -5 |
| 2022-01-12 | -20 |
原代码问题分析
原代码存在两个关键错误:
- 在
group_by(date)后的summarise中,直接使用A[,2:4]会引用整个原始数据框的列,而非当前分组的子集,导致滚动窗口计算逻辑错误。 width = window传入的是整个window列,而每组的window值是统一的,应该取每组的单一窗口值(比如window[1])。
正确解决方案
使用分组后的当前数据子集,指定正确的窗口宽度,再对滚动窗口的结果取全局最小值:
A %>% group_by(date) %>% summarise( MINS = min(rollapply( select(cur_data(), a, b, c), # 获取当前分组的a、b、c列 width = window[1], # 取当前分组的统一窗口宽度 FUN = min, by.column = FALSE, # 将窗口内所有跨列元素合并为一个向量求最小值 align = "right" # 默认右对齐窗口,可按需调整 )) )
执行后得到目标结果:
# A tibble: 2 × 2 date MINS <date> <dbl> 1 2022-01-01 -5 2 2022-01-12 -20
代码说明
cur_data():在分组操作中直接获取当前分组的数据子集,避免误引用整个原始数据框。window[1]:由于每组内的window值完全一致,取第一个元素即可代表该组的窗口宽度。by.column = FALSE:让rollapply忽略列的划分,将每个滚动窗口内的所有元素合并为一个向量计算最小值。- 外层
min():对所有滚动窗口的最小值再次取最小,得到该分组的全局最小。
内容的提问来源于stack exchange,提问作者Homer Jay Simpson
相关产品推荐
相关产品推荐

