R语言按多列分组生成逐小时时间序列报错求解
报错原因
- 核心问题是
mutate()的规则限制:该函数要求分组内计算生成的新列长度,必须和分组原始行数完全相等。你的每个分组仅1行原始数据,但逐小时seq()生成的序列长度为48/72行,长度不匹配直接触发报错。 - 额外隐患:直接调用
as.POSIXct()转换日期未指定格式,你传入的日期是月/日/年结构,默认解析逻辑可能出现日期识别错误。
正确实现代码
推荐使用dplyr 1.1.0及以上版本自带的reframe()实现,该函数原生支持分组后返回任意行数的计算结果,逻辑最简洁:
library(dplyr) library(lubridate) # 用于方便做日期偏移计算,也可手动计算时间差替代 # 构造输入表 Gender = c("Male","Female") Sec = c("AA","BB") min_date = c("12/1/2018","12/9/2018") max_date = c("12/3/2018","12/10/2018") df_in = data.frame(Gender,Sec,min_date,max_date) # 生成目标结果集 df_out <- df_in %>% # 先把字符串日期转为标准时间格式,明确指定月/日/年的解析规则 mutate( min_date = as.POSIXct(min_date, format = "%m/%d/%Y"), max_date = as.POSIXct(max_date, format = "%m/%d/%Y") ) %>% group_by(Gender, Sec) %>% # 用reframe替代mutate,生成分组逐小时序列 # 结束时间偏移23小时,保证每组行数符合预期:3天*24=72行、2天*24=48行 reframe( DateSeries = seq( from = min_date, to = max_date + days(1) - hours(1), by = "hour" ) )
老版本兼容方案
如果你的dplyr版本低于1.1.0没有reframe(),可以用purrr+tidyr的嵌套展开逻辑实现,结果完全一致:
library(dplyr) library(tidyr) library(purrr) library(lubridate) df_out <- df_in %>% mutate( min_date = as.POSIXct(min_date, format = "%m/%d/%Y"), max_date = as.POSIXct(max_date, format = "%m/%d/%Y"), # 逐行生成时间序列存为列表列 DateSeries = map2( min_date, max_date, ~seq(.x, .y + days(1) - hours(1), by = "hour") ) ) %>% # 展开列表列得到逐行结果 unnest(DateSeries) %>% select(Gender, Sec, DateSeries)
校验说明:运行后
Male+AA分组对应时间从2018-12-01 00:00:00到2018-12-03 23:00:00共72行,Female+BB分组对应时间从2018-12-09 00:00:00到2018-12-10 23:00:00共48行,完全匹配需求。
内容的提问来源于stack exchange,提问作者san1
相关产品推荐
相关产品推荐

