如何在R中使用data.table对面板数据的两类数据求和合并
解决R中面板数据的城市-州级别汇总问题
假设你的年度面板数据里,Dep列包含州级条目(如A、B)和属于州A的两个城市条目a、b,需要将每年a和b的Homicides数值求和,合并为州A的条目,最终得到统一州级的数据集。以下是具体实现方法:
先构造示例数据
方便你对照测试,先模拟符合场景的数据:
library(dplyr) panel_data <- tibble( Year = rep(2018:2020, each = 4), Dep = rep(c("A", "a", "b", "B"), 3), Homicides = c(NA, 12, 8, 25, NA, 15, 10, 28, NA, 18, 12, 30) )
这里州A的原始行设为NA(实际数据里可能没有这条,或者为空),城市a、b有具体的凶杀数据,州B是完整的州级数据。
核心处理步骤
1. 映射城市到所属州
先把需要合并的城市a、b关联到州A,生成新的分组列:
# 定义城市-州映射关系 city_to_state <- c("a" = "A", "b" = "A") # 生成新的分组列:a、b替换为A,其他保持原Dep值 panel_data <- panel_data %>% mutate(Dep_group = ifelse(Dep %in% names(city_to_state), city_to_state[Dep], Dep))
2. 按年度和新分组汇总数据
按年份和新的州分组,对Homicides求和,同时处理空值:
# 汇总计算,并重命名列回原始的Dep final_data <- panel_data %>% group_by(Year, Dep_group) %>% summarise(Homicides = sum(Homicides, na.rm = TRUE), .groups = "drop") %>% rename(Dep = Dep_group)
3. 清理无效行(可选)
如果原始数据里有州A的空行(求和后为0的情况),可以过滤掉:
final_data <- final_data %>% filter(!(Dep == "A" & Homicides == 0))
完整可运行代码
library(dplyr) # 构造示例数据 panel_data <- tibble( Year = rep(2018:2020, each = 4), Dep = rep(c("A", "a", "b", "B"), 3), Homicides = c(NA, 12, 8, 25, NA, 15, 10, 28, NA, 18, 12, 30) ) # 映射分组并汇总 city_to_state <- c("a" = "A", "b" = "A") final_data <- panel_data %>% mutate(Dep_group = ifelse(Dep %in% names(city_to_state), city_to_state[Dep], Dep)) %>% group_by(Year, Dep_group) %>% summarise(Homicides = sum(Homicides, na.rm = TRUE), .groups = "drop") %>% rename(Dep = Dep_group) %>% filter(!(Dep == "A" & Homicides == 0)) print(final_data)
运行后输出的final_data就是你需要的格式:每年一行州A(a+b的凶杀数之和),同时保留州B的原始数据。
补充:处理其他变量
如果数据里还有其他需要保留的变量(比如Population),可以在summarise里添加对应逻辑,比如城市人口求和:
final_data <- panel_data %>% mutate(Dep_group = ifelse(Dep %in% names(city_to_state), city_to_state[Dep], Dep)) %>% group_by(Year, Dep_group) %>% summarise( Homicides = sum(Homicides, na.rm = TRUE), Population = sum(Population, na.rm = TRUE), .groups = "drop" ) %>% rename(Dep = Dep_group)
大数据场景优化
如果你的面板数据量很大,用data.table处理效率更高:
library(data.table) setDT(panel_data) panel_data[, Dep_group := fifelse(Dep %in% c("a", "b"), "A", Dep)] final_data <- panel_data[, .(Homicides = sum(Homicides, na.rm = TRUE)), by = .(Year, Dep_group)] setnames(final_data, "Dep_group", "Dep")
内容的提问来源于stack exchange,提问作者John M. Riveros
相关产品推荐
相关产品推荐

