如何循环遍历连续时间段计算16天周期内超20℃天数
问题需求
需要遍历数据集内所有75个16天滑动窗口周期,每个周期相较于前一个整体后移1天,统计每个周期内Nor_MM≥20℃的天数。目前仅能计算单个周期的结果,虽已添加儒略日列简化日期处理,但仍未实现循环滑动的逻辑。
示例数据
数据预览
| Date | Nor_MM | Julianday |
|---|---|---|
| 2090-06-01 | 22.58582 | 152 |
| 2090-06-02 | 20.43654 | 153 |
| 2090-06-03 | 17.37954 | 154 |
| 2090-06-04 | 18.12772 | 155 |
| 2090-06-05 | 19.53053 | 156 |
| 2090-06-06 | 23.25154 | 157 |
| 2090-06-07 | 24.52292 | 158 |
| 2090-06-08 | 24.83597 | 159 |
| 2090-06-09 | 24.67915 | 160 |
| 2090-06-10 | 24.22688 | 161 |
R数据结构
structure(list(Date = structure(c(43981, 43982, 43983, 43984, 43985, 43986, 43987, 43988, 43989, 43990), class = "Date"), Nor_MM = c(22.58582103, 20.43654256, 17.37954095, 18.12772066, 19.53053131, 23.25153522, 24.52291687, 24.83597434, 24.67915157, 24.22688304), Julianday = c(152, 153, 154, 155, 156, 157, 158, 159, 160, 161)), row.names = 6441:6450, class = "data.frame")
注:原数据结构中
2090-01为笔误,已修正为对应日期的数值43981
现有单个周期计算代码
目前可通过以下代码计算单个16天周期(如2090-06-01至2090-06-16)的统计结果:
df1 <- filter_time(df, time_formula = '2090-06-01' ~ '2090-06-16') sum(df1$Nor_MM >= 20)
解决方案
方法1:基于儒略日的循环实现
利用儒略日的连续性,遍历所有可能的窗口起始点,逐个计算统计值:
# 获取所有有效窗口的起始儒略日(结束儒略日=起始+15,确保窗口为16天) start_julian <- min(df$Julianday):(max(df$Julianday) - 15) # 初始化存储结果的向量 count_result <- numeric(length(start_julian)) # 循环遍历每个窗口 for(i in seq_along(start_julian)){ current_start <- start_julian[i] current_end <- current_start + 15 # 筛选当前窗口内的数据 window_data <- df[df$Julianday >= current_start & df$Julianday <= current_end, ] # 统计Nor_MM≥20的天数 count_result[i] <- sum(window_data$Nor_MM >= 20) } # (可选)将结果与窗口的起止日期对应,生成结果表 window_result <- data.frame( start_date = df$Date[match(start_julian, df$Julianday)], end_date = df$Date[match(start_julian + 15, df$Julianday)], days_ge20 = count_result )
方法2:滑动窗口高效计算(推荐)
使用zoo包的rollapply函数实现滑动窗口求和,比循环更高效,适合大数据集:
# 先将Nor_MM≥20标记为1,否则为0 mm_flag <- as.integer(df$Nor_MM >= 20) # 加载zoo包(若未安装先运行install.packages("zoo")) library(zoo) # 计算16天滑动窗口内的求和结果,align="left"表示窗口从当前行开始向后取16天 count_roll <- rollapply(mm_flag, width = 16, FUN = sum, align = "left") # 生成带日期的结果表 window_result_roll <- data.frame( start_date = df$Date[1:(nrow(df)-15)], end_date = df$Date[16:nrow(df)], days_ge20 = count_roll )
内容的提问来源于stack exchange,提问作者Ellie Rose
相关产品推荐
相关产品推荐

