如何在R中基于跨年度日期范围为新列分配生长率?
问题:将日生长率分配到自定义年度时间框架(8月1日至次年7月31日)
需要将基于年度4次个体测量计算出的日生长率,分配到自定义时间框架Year2(定义为第N-1年8月1日至第N年7月31日,对应Year2=N)。现有代码无法处理跨Year2边界的测量区间,需实现生长量的拆分与准确分配。
现有数据
| ID | Date | Year | Year2 | Lag | Lapse | Growth | Daily_growth |
|---|---|---|---|---|---|---|---|
| 1 | 2009-07-30 | 2009 | 2009 | NA | NA | 35.004 | NA |
| 1 | 2009-10-29 | 2009 | 2010 | 2009-07-30 | 91 days | 31.585 | 0.347 |
| 1 | 2010-01-27 | 2010 | 2010 | 2009-10-29 | 90 days | 63.769 | 0.709 |
| 1 | 2010-04-27 | 2010 | 2010 | 2010-01-27 | 90 days | 28.329 | 0.315 |
| 1 | 2010-07-29 | 2010 | 2010 | 2010-04-27 | 93 days | 32.068 | 0.345 |
| 1 | 2010-11-02 | 2010 | 2011 | 2010-07-29 | 96 days | 128.1617320 | 1.335 |
现有生长率计算代码
Growth_df <- Growth_df%>% group_by(ID) %>% # 按个体分组 mutate(Lag = lag(Date), # 上一次测量日期 Lapse = round(difftime(Date, Lag, units = "days")), # 两次测量间隔天数 Daily_growth = as.numeric(Growth) / as.numeric(Lapse))
解决方案
核心思路是:将每个测量区间(Lag到Date)拆分为与Year2时间框架重叠的部分,计算每部分的生长量后,按Year2分组求和。
完整代码
library(dplyr) library(lubridate) library(tidyr) # 1. 预处理数据:统一日期格式,过滤无前置测量的行 Growth_df_clean <- Growth_df %>% mutate(across(c(Date, Lag), ymd)) %>% filter(!is.na(Lag)) # 2. 拆分跨Year2的测量区间,计算每个区间对对应Year2的生长贡献 Growth_df_split <- Growth_df_clean %>% rowwise() %>% mutate( # 计算测量区间起始和结束对应的Year2 start_year2 = floor_date(Lag, "year", offset = months(7)) %>% year(), end_year2 = floor_date(Date, "year", offset = months(7)) %>% year(), # 生成该测量区间覆盖的所有Year2列表 year2_list = list(start_year2:end_year2) ) %>% unnest(year2_list) %>% rename(Year2 = year2_list) %>% # 生成当前Year2的时间边界 mutate( year2_start = ymd(paste0(Year2 - 1, "-08-01")), year2_end = ymd(paste0(Year2, "-07-31")), # 计算测量区间与Year2区间的重叠部分 overlap_start = pmax(Lag, year2_start), overlap_end = pmin(Date, year2_end), overlap_days = as.numeric(overlap_end - overlap_start + 1), overlap_days = ifelse(overlap_days < 0, 0, overlap_days), # 计算该部分的生长贡献 growth_contribution = Daily_growth * overlap_days ) # 3. 按ID和Year2分组,计算每个Year2的总生长量 Year2_total_growth <- Growth_df_split %>% group_by(ID, Year2) %>% summarise(Year2_growth = sum(growth_contribution, na.rm = TRUE), .groups = "drop") # 4. (可选)将结果合并回原数据框 Growth_df <- Growth_df %>% left_join(Year2_total_growth, by = c("ID", "Year2"))
代码解释
- 日期预处理:确保
Date和Lag为日期格式,过滤无前置测量的首行数据。 - 拆分跨区间测量:
- 用
floor_date结合offset = months(7),将日期转换为对应的Year2(以8月1日为年度起始)。 - 生成测量区间覆盖的
Year2列表,通过unnest将单个观测拆分为对应多个Year2的行。
- 用
- 计算重叠天数:对每个拆分后的行,计算测量区间与
Year2区间的重叠天数,确保只统计Year2时间框架内的天数。 - 汇总生长量:按
ID和Year2分组求和,得到每个自定义年度的总生长量。
这个方法自动处理跨Year2边界的测量区间,确保生长量准确分配到对应的时间框架中。
内容的提问来源于stack exchange,提问作者KellyForrester
相关产品推荐
相关产品推荐

