多日期范围DataFrame关联匹配:按日期匹配Anzahl列
问题:按日期范围匹配关联DataFrame的数值列
现有liste DataFrame结构如下:
> liste Datum Verfahren Fachgebiet Praxis Rang 1 2025-04-09 0 0 0 17 2 2025-04-09 0 0 0 56 3 2025-07-12 0 0 0 200 4 2025-04-14 0 0 0 7 5 2025-04-14 0 0 0 167 6 2025-04-14 0 1 0 208
需根据liste每行的Datum日期,匹配对应日期范围的kombinationen DataFrame中的Anzahl值。这些kombinationen结构一致,仅Anzahl值随日期范围变化。
当前多次执行merge的代码会导致列重复(如Anzahl.x、Anzahl.y)且丢失部分行,不符合预期。预期结果是每行根据Datum匹配对应日期范围的Anzahl:
> liste Datum Verfahren Fachgebiet Praxis Rang Anzahl 1 2025-04-09 0 0 0 17 231 2 2025-04-09 0 0 0 56 231 3 2025-07-12 0 0 0 200 233 <- changed value 4 2025-04-14 0 0 0 7 231 5 2025-04-14 0 0 0 167 231 6 2025-04-14 0 1 0 208 188
错误原因分析
原循环代码存在以下问题:
- 每次
merge都会生成新的Anzahl列,导致列重复堆积 - 使用
subset(liste, Datum <= i[[1]])会过滤掉当前日期范围外的行,最终丢失部分原始数据 - 循环中不断覆盖
liste,导致数据被错误叠加
解决方案
方法1:基础R实现
步骤:
- 将所有日期对应的
kombinationen整合为带日期标记的完整数据集 - 为
liste每行找到最大的不超过该行Datum的关联日期 - 根据匹配的日期和关联列(Verfahren、Fachgebiet、Praxis)合并
Anzahl值
代码实现:
# 1. 构造完整的日期关联数据集 kombinationen_full <- do.call(rbind, lapply(anzahl, function(x) { df <- kombinationen df$Anzahl <- x[[2]] df$Geltungsdatum <- as.Date(x[[1]]) df })) # 2. 转换liste的Datum为日期类型 liste$Datum <- as.Date(liste$Datum) # 3. 为每行匹配对应生效日期 liste$matched_date <- mapply(function(d) { max(kombinationen_full$Geltungsdatum[kombinationen_full$Geltungsdatum <= d]) }, liste$Datum) # 4. 合并数据并整理列 result <- merge(liste, kombinationen_full, by.x = c("Verfahren", "Fachgebiet", "Praxis", "matched_date"), by.y = c("Verfahren", "Fachgebiet", "Praxis", "Geltungsdatum"), all.x = TRUE) result <- result[, c("Datum", "Verfahren", "Fachgebiet", "Praxis", "Rang", "Anzahl")]
方法2:dplyr + lubridate实现(更简洁)
library(dplyr) library(lubridate) # 构造完整的日期关联数据集 kombinationen_full <- bind_rows(lapply(anzahl, function(x) { kombinationen %>% mutate(Anzahl = x[[2]], Geltungsdatum = ymd(x[[1]])) })) # 匹配并合并数据 result <- liste %>% mutate(Datum = ymd(Datum)) %>% rowwise() %>% mutate(matched_date = max(kombinationen_full$Geltungsdatum[kombinationen_full$Geltungsdatum <= Datum])) %>% ungroup() %>% left_join(kombinationen_full, by = c("Verfahren", "Fachgebiet", "Praxis", "matched_date" = "Geltungsdatum")) %>% select(Datum, Verfahren, Fachgebiet, Praxis, Rang, Anzahl)
验证结果
运行上述代码后,得到的result即为预期格式:
> result Datum Verfahren Fachgebiet Praxis Rang Anzahl 1 2025-04-09 0 0 0 17 231 2 2025-04-09 0 0 0 56 231 3 2025-07-12 0 0 0 200 233 4 2025-04-14 0 0 0 7 231 5 2025-04-14 0 0 0 167 231 6 2025-04-14 0 1 0 208 188
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

