合并大型data.frame填补缺失小时级日期的问题排查
解决小时级时间序列缺失值填补的merge问题
你遇到的核心问题是合并键不够精确——你只使用了date(日期)作为合并依据,但你的目标是小时级的匹配,这就导致merge无法把ndays里的每个小时行和x1中对应的小时记录对应起来,反而产生了笛卡尔积或者匹配错误。
问题拆解
你的x1数据只有日期(date列,Date类型),但没有小时信息;而ndays是完整的小时级序列(每个日期对应24行,每行对应一个小时)。当你仅按date合并时:
- 用
all.x=T时,ndays的每个小时行都会匹配x1中该日期的所有行,导致value列要么重复填充,要么因为匹配逻辑出现NA; - 用
all=T时,会得到两个数据集的笛卡尔积,行数自然远超8760的预期。
正确的解决步骤
要实现精确的小时级匹配,你需要先给x1补充小时信息,然后用date+hour作为合并键:
步骤1:给x1添加小时列
假设你的x1是按时间顺序排列的(每个日期的24小时记录连续排列),可以用以下代码生成小时列:
# 给x1添加小时列,每个日期对应00:00:00到23:00:00的小时 x1$hour <- rep(format(seq(0, 23), "%H:%M:%S"), length(unique(x1$date)))
步骤2:使用双键合并
现在用date和hour同时作为合并键,就能精准匹配每个小时的记录:
newdata <- merge(ndays, x1, by = c("date", "hour"), all.x = TRUE)
这样得到的newdata就是全年8760行的完整小时序列,x1中存在的小时会填充对应的value,缺失的小时则为NA,完全符合你的预期。
更简洁的替代方案(用tidyverse)
如果你熟悉tidyverse工具链,用tidyr::complete可以更高效地完成这个任务,不需要手动生成完整序列:
library(tidyverse) library(lubridate) # 先把x1的日期和小时合并为完整的datetime x1 <- x1 %>% group_by(date) %>% # 按顺序生成当天的小时时间戳 mutate(datetime = seq(ymd_hms(paste(date, "00:00:00")), ymd_hms(paste(date, "23:00:00")), by = "hour")) %>% ungroup() # 生成完整的小时序列并填充缺失值 newdata <- x1 %>% complete(datetime = seq(ymd_hms("2010-01-01 00:00:00"), ymd_hms("2010-12-31 23:00:00"), by = "hour")) %>% # 可选:拆分回date和hour列 mutate(date = as.Date(datetime), hour = format(datetime, "%H:%M:%S")) %>% select(date, hour, value)
总结
你之前忽略了小时级匹配需要同时用到日期和小时作为合并键,仅用日期会导致匹配精度不够。补充小时信息后,无论是用基础R的merge还是tidyverse的工具,都能轻松得到你想要的完整序列。
内容的提问来源于stack exchange,提问作者user3231352
相关产品推荐
相关产品推荐

