如何用R按年度计算不同起止日期区间内的GDD总和
解决方案
可以通过关联生长季起止数据与每日GDD数据,结合跨年情况的逻辑判断,用dplyr快速计算每年生长季的GDD总和。以下是两种实用方法:
方法一:基于儒略日的逻辑判断(忽略闰年)
适合数据量不大、无需考虑闰年的场景,直接通过年份和儒略日的逻辑匹配筛选数据:
library(dplyr) # 假设生长季数据框为season_dates,每日GDD数据框为daily_gdd gdd_season_total <- season_dates %>% rowwise() %>% mutate( # 计算当前生长季的GDD总和,处理跨年情况 total_GDD = sum( daily_gdd$GDD[ # 非跨年生长季:日期在当年起止范围内 (daily_gdd$Year == Year & daily_gdd$Julian_day >= Onset_date & daily_gdd$Julian_day <= Cessation_date) | # 跨年生长季:包含当年起始日之后的日期,以及下一年终止日之前的日期 (daily_gdd$Year == Year + 1 & daily_gdd$Julian_day <= Cessation_date & Onset_date > Cessation_date) ], na.rm = TRUE ) ) %>% ungroup() %>% select(Year, total_GDD) # 保留需要的结果列
方法二:基于实际日期的精准判断(支持闰年)
如果需要考虑闰年的天数差异,结合lubridate包将儒略日转为实际日期,再进行区间筛选:
library(dplyr) library(lubridate) # 转换生长季起止儒略日为实际日期 season_dates <- season_dates %>% mutate( onset_date = ymd(paste(Year, 1, 1)) + days(Onset_date - 1), cessation_date = if_else( Onset_date <= Cessation_date, ymd(paste(Year, 1, 1)) + days(Cessation_date - 1), ymd(paste(Year + 1, 1, 1)) + days(Cessation_date - 1) ) ) # 转换每日GDD的儒略日为实际日期 daily_gdd <- daily_gdd %>% mutate(date = ymd(paste(Year, 1, 1)) + days(Julian_day - 1)) # 关联数据并筛选生长季内的GDD,按年求和 gdd_season_total <- daily_gdd %>% cross_join(season_dates) %>% filter(date >= onset_date & date <= cessation_date) %>% group_by(Year = season_dates$Year) %>% summarise(total_GDD = sum(GDD, na.rm = TRUE))
关键说明
- 两种方法都处理了跨年生长季的情况(比如1950年起始日366、终止日108,对应1950年最后一天到1951年第108天)
na.rm = TRUE用于避免因部分年份无匹配数据导致的求和结果为NA
内容的提问来源于stack exchange,提问作者Seluuu
相关产品推荐
相关产品推荐

