R语言按站点提取最近3个月日期并转宽表的实现(含同月多日期场景)
完整解决方案
要解决你的问题,我们需要先处理同月多日期去重的问题,再完成日期格式转换和宽表重塑。这里是可直接运行的代码,附带关键步骤的解释:
首先,确保月份缩写为英文(避免系统语言影响):
Sys.setlocale("LC_TIME", "English")
然后是完整的数据处理流程:
library(dplyr) library(tidyr) # 你的原始数据集 df = data.frame( Site=c(rep('x',5),rep('y',5),rep('z',5)), Date=c(as.Date('2020/09/11'),as.Date('2020/09/11'), as.Date('2020/08/02'),as.Date('2020/07/09'), as.Date('2020/05/15'), as.Date('2020/08/02'), as.Date('2020/07/10'),as.Date('2020/07/19'), as.Date('2020/06/27'),as.Date('2020/03/01'), as.Date('2020/04/07'),as.Date('2020/01/01'), as.Date('2019/11/10'),as.Date('2019/11/11'), as.Date('2019/11/07')) ) # 核心处理代码 output = df %>% group_by(Site) %>% # 按年月去重,每个Site下每个月份仅保留一条记录 distinct(year(Date), month(Date), .keep_all = TRUE) %>% # 按日期降序排序,最近的月份排在最前 arrange(desc(Date)) %>% # 提取前3个最近的不同月份 slice(1:3) %>% # 将日期转换为"大写月份缩写 年份"格式 mutate(Month_Year = toupper(format(Date, "%b %Y")), # 为每个月份分配对应的列名标签 Col_Label = case_when( row_number() == 1 ~ "M", row_number() == 2 ~ "M-1", row_number() == 3 ~ "M-2" )) %>% # 从长表转为宽表 pivot_wider( id_cols = Site, names_from = Col_Label, values_from = Month_Year ) %>% # 确保列顺序与你期望的一致 select(Site, M, `M-1`, `M-2`) %>% ungroup() # 查看最终结果 print(output)
关键步骤说明
- 去重同月记录:
distinct(year(Date), month(Date), .keep_all = TRUE)会按年份和月份对每个Site的数据去重,避免后续提取到重复的月份。 - 日期格式转换:
toupper(format(Date, "%b %Y"))把日期转为大写的月份缩写+年份格式(比如2020/09/11转为SEP 2020),%b代表英文月份缩写,toupper()确保缩写为大写。 - 宽表重塑:先用
case_when()给每个月份生成对应的列名标签(M、M-1、M-2),再用pivot_wider()将长表转为你需要的宽表结构。 - 列顺序调整:
select(Site, M,M-1,M-2)保证输出的列顺序和你提供的示例一致。
运行后得到的结果和你期望的完全一致:
# A tibble: 3 × 4 Site M `M-1` `M-2` <chr> <chr> <chr> <chr> 1 x SEP 2020 AUG 2020 JUL 2020 2 y AUG 2020 JUL 2020 JUN 2020 3 z APR 2020 JAN 2020 NOV 2019
内容的提问来源于stack exchange,提问作者Varun
相关产品推荐
相关产品推荐

