在R中计算按小时分组、满足当日湿度范围的Reg变量5日滚动平均值
问题描述
这是我首次在Stackoverflow提问,若有疏漏或错误请见谅。
我拥有一份时间序列数据集,需按每日特定小时,计算二进制变量Reg的5日滚动平均值。可通过以下代码生成示例数据:
library(dplyr) library(zoo) set.seed(69) df <- data.frame(Hour = rep(c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24), times = 10), Reg = rep(round(runif(24*10, 0, 1))), HumidityLevel = rep(runif(24*10, 0, 100))) df_ranges <- data.frame(LowerRange = rep(cbind(rollapply(df$HumidityLevel, 24, min, by = 24)), each = 24) ,UpperRange = rep(cbind(rollapply(df$HumidityLevel, 24, max, by = 24)), each = 24)) df <- cbind(df, df_ranges)
我已通过以下代码计算出简单滚动平均值:
df <- df %>% group_by(Hour) %>% mutate(AvgReg = lag(rollapplyr(Reg, 5, mean, na.rm = T, partial = T), n = 1))
我需要实现的是:仅使用满足HumidityLevel处于当日对应范围(由LowerRange和UpperRange列确定,该范围为当日HumidityLevel的最值)的历史行,计算Reg的滚动平均值。
例如,某一天的湿度范围为20至54,则该天1小时的滚动平均值需使用之前所有1小时观测中HumidityLevel在20至54之间的Reg值计算。
期望输出如下:
desired_output <- data.frame(RowNum = c(1:10), Hour = rep(1, times = 10), Reg = c(1,0,0,1,0,1,0,0,0,0), HumidityLevel = c(28.36, 65.02, 1.12, 49.61, 24.50, 98.16, 77.33, 97.03, 47.03, 85.71), LowerBoundary = c(5.67, 7.50, 1.12, 19.32, 0.01, 6.94, 7.48, 0.71, 2.85, 1.59), UpperBoundary = c(93.60, 89.37, 97.25, 99.63, 91.92, 98.16, 98.48, 99.98, 99.70, 98.86), AvgReg = c("NA", 1, 0.5, 0.5, 0.5, 0.5, 0.6, 0.4, 0.4, 0.2))
解决方案
要实现按小时分组,仅筛选历史中湿度落在当日对应范围的记录来计算Reg的滚动平均值,可以结合dplyr的分组操作和自定义函数处理。核心逻辑是对每个小时组内的每一行,回溯所有历史行,筛选出符合湿度范围条件的Reg值后计算均值。
代码实现
library(dplyr) library(zoo) # 生成示例数据 set.seed(69) df <- data.frame(Hour = rep(c(1:24), times = 10), Reg = round(runif(24*10, 0, 1)), HumidityLevel = runif(24*10, 0, 100)) df_ranges <- data.frame(LowerRange = rep(rollapply(df$HumidityLevel, 24, min, by = 24), each = 24), UpperRange = rep(rollapply(df$HumidityLevel, 24, max, by = 24), each = 24)) df <- cbind(df, df_ranges) # 自定义函数:计算当前行符合条件的滚动均值 calc_filtered_avg <- function(row_idx, group_data) { # 获取当前行的湿度范围 current_lower <- group_data$LowerRange[row_idx] current_upper <- group_data$UpperRange[row_idx] # 提取同小时组内的历史行(当前行之前的记录) history_data <- group_data[1:(row_idx-1), ] # 筛选湿度在当前范围内的Reg值 filtered_reg <- history_data$Reg[history_data$HumidityLevel >= current_lower & history_data$HumidityLevel <= current_upper] # 返回均值,无符合条件记录则返回NA if (length(filtered_reg) == 0) { return(NA) } else { return(mean(filtered_reg)) } } # 按Hour分组计算符合要求的滚动平均值 df <- df %>% group_by(Hour) %>% mutate(AvgReg = sapply(1:n(), function(i) calc_filtered_avg(i, cur_data()))) %>% ungroup()
代码说明
- 自定义函数
calc_filtered_avg:针对组内每一行,提取当前行的湿度范围,筛选同小时组内所有历史行中湿度符合该范围的Reg值,计算均值;若没有符合条件的历史记录,返回NA。 - 分组应用函数:通过
sapply遍历每个小时组内的所有行,调用自定义函数计算对应的滚动平均值,最终生成符合要求的AvgReg列。
结果验证
可以筛选Hour == 1的记录,与你提供的desired_output对比,确认计算逻辑的正确性。
内容的提问来源于stack exchange,提问作者Hans Peter
相关产品推荐
相关产品推荐

