You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言如何基于另一张表按分组扩展data.frame数据

R实现按分组补全周度序列方案

方法一:tidyverse实现(推荐,代码简洁易维护)

首先加载依赖包:

library(dplyr)
library(tidyr)

步骤1:构造全量周度集合

把原数据已有的周度和待扩展的周度合并去重,得到完整的周列表:

all_weeks <- unique(c(df$range_key, extended_week$range_key))

注意:因为range_key是w+两位周数+四位年份的字符串格式,直接做字符串排序/比较会出现跨年顺序错误(比如w522022会被判定为大于w012023),建议先做顺序校正:

all_weeks <- tibble(range_key = all_weeks) %>%
  # 拼接为“年份+周数”的数值格式,方便正确排序
  mutate(sort_id = as.numeric(sub("w(\\d{2})(\\d{4})", "\\2\\1", range_key))) %>%
  arrange(sort_id) %>%
  pull(range_key)

步骤2:按分组补全周度

根据你的业务需求二选一即可:

  • 需求1:每个(id, country, case)分组,覆盖从最早周(w232022)到w522026的全部周度
result <- df %>%
  complete(id, country, case, range_key = all_weeks) %>%
  # 按id、周度、case排序,方便查看
  arrange(id, range_key, case)
  • 需求2:每个(id, country, case)分组,仅覆盖从该分组第一次出现的周到w522026的周度(比如case=B最早出现在w242022,就不需要补w232022的B记录)
result <- df %>%
  group_by(id, country, case) %>%
  # 记录每个分组最早出现的周
  mutate(min_week = min(range_key)) %>%
  ungroup() %>%
  complete(id, country, case, range_key = all_weeks) %>%
  # 过滤掉分组出现前的无效周
  filter(range_key >= min_week) %>%
  select(-min_week) %>%
  arrange(id, range_key, case)

小提示:如果原df除了4个核心字段还有其他指标字段,补全后缺失值如果需要按分组向前填充,可以在complete后加group_by(id, country, case) %>% fill(everything(), .direction = "down")实现。

方法二:基础R实现(无需安装第三方包)

如果不想加载tidyverse,可以用基础R的合并功能实现,逻辑和上面一致:

# 1. 获取所有唯一的分组组合
unique_groups <- unique(df[, c("id", "country", "case")])
# 2. 构造全量周集合(需要做顺序校正可以参考上面的逻辑自行处理)
all_weeks <- unique(c(df$range_key, extended_week$range_key))
# 3. 构造分组+周度的全量笛卡尔积
full_combination <- merge(unique_groups, data.frame(range_key = all_weeks), by = NULL)
# 4. 和原数据左连接,保留原有记录
result <- merge(
  full_combination, 
  df, 
  by = c("id", "country", "case", "range_key"), 
  all.x = TRUE
)
# 5. 排序得到最终结果
result <- result[order(result$id, result$range_key, result$case), ]

内容的提问来源于stack exchange,提问作者user

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 03:49:13