含缺失值面板数据:最大化连续年份或国家数量的编码实现
面板数据平衡筛选:两种核心策略的R实现
我有一份覆盖15年的国家面板数据,存在缺失值,需要编写R代码实现两种平衡面板筛选策略:
- 策略一:以减少连续观测年份为代价,最大化观测国家数量
- 策略二:以减少观测国家数量为代价,最大化连续观测年份
示例数据场景说明
- 最大化连续年份:可得到2002-2003年共2年、6个国家(Country1、Country2、Country4、Country5、Country7、Country8)的数据集
- 最大化国家数量:可选2003年(仅缺失Country3)或2005年(仅缺失Country2),均可得到9个国家、1年的数据集
示例面板数据
df <- structure(list(country = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L, 6L, 7L, 7L, 7L, 7L, 7L, 8L, 8L, 8L, 8L, 8L, 9L, 9L, 9L, 9L, 9L, 10L, 10L, 10L, 10L, 10L), levels = c("Country1", "Country2", "Country3", "Country4", "Country5", "Country6", "Country7", "Country8", "Country9", "Country10"), class = "factor"), year = c(2001L, 2002L, 2003L, 2004L, 2005L, 2001L, 2002L, 2003L, 2004L, 2005L, 2001L, 2002L, 2003L, 2004L, 2005L, 2001L, 2002L, 2003L, 2004L, 2005L, 2001L, 2002L, 2003L, 2004L, 2005L, 2001L, 2002L, 2003L, 2004L, 2005L, 2001L, 2002L, 2003L, 2004L, 2005L, 2001L, 2002L, 2003L, 2004L, 2005L, 2001L, 2002L, 2003L, 2004L, 2005L, 2001L, 2002L, 2003L, 2004L, 2005L), x = c(NA, 0.494188331267827, -0.681660478755657, -0.652094780680999, -1.28630053043433, 1.68217608051942, -0.177330482269606, -0.324270272246319, -0.0568967778473925, NA, -0.635736453948977, -0.505957462114257, NA, NA, 0.450187101272656, -0.461644730360566, 1.34303882517041, -0.588894486259664, NA, -0.018559832714638, NA, -0.214579408546869, 0.531496192632572, NA, -0.318068374543844, -0.508055079939179, NA, -1.51839408178679, -0.463530401472386, -0.929362147453702, NA, -0.100190741213562, 0.306557860789766, NA, -1.48746031014148, NA, 0.712666307051405, -1.53644982353759, NA, -1.07519229661568, -0.319992868548507, NA, -0.300976126836611, NA, 1.00002880371391, NA, NA, -0.528279904445006, 0.0173956196932517, -0.621266694796823)), out.attrs = list(dim = c(country = 10L, year = 5L), dimnames = list(country = c("country=Country1", "country=Country2", "country=Country3", "country=Country4", "country=Country5", "country=Country6", "country=Country7", "country=Country8", "country=Country9", "country=Country10" ), year = c("year=2001", "year=2002", "year=2003", "year=2004", "year=2005"))), row.names = c(NA, -50L), class = "data.frame") # 可视化缺失值分布 library(panelView) panelview(data = df, Y = "x", type = "missing", index = c("country", "year"))
策略一:最大化观测国家数量
逻辑
统计每个年份中拥有非缺失值的国家数量,筛选出国家数量最多的年份(若多个年份数量相同,全部保留),得到对应年份的所有非缺失数据。
代码实现
library(dplyr) # 1. 统计各年份的非缺失国家数 year_country_count <- df %>% filter(!is.na(x)) %>% group_by(year) %>% summarize(country_n = n_distinct(country)) %>% ungroup() # 2. 找出最大的国家数量 max_country_n <- max(year_country_count$country_n) # 3. 筛选对应年份的非缺失数据 balanced_max_countries <- df %>% filter(year %in% year_country_count$year[year_country_count$country_n == max_country_n], !is.na(x)) # 查看结果 balanced_max_countries %>% group_by(year) %>% summarize(country_count = n_distinct(country))
结果说明
运行后会得到国家数量最多的年份数据,示例中为2003年和2005年,各9个国家。
策略二:最大化连续观测年份
逻辑
- 对每个国家,找出所有连续的非缺失年份区间
- 枚举所有可能的连续年份区间,统计每个区间内全程无缺失的国家数量
- 优先选择长度最长的区间;若区间长度相同,选择覆盖国家最多的区间
- 筛选该区间内的所有国家数据
代码实现
# 1. 为每个国家生成连续非缺失年份的区间 country_continuous_intervals <- df %>% filter(!is.na(x)) %>% arrange(country, year) %>% group_by(country) %>% # 标记连续年份组:当前年份与前一年差1则同组,否则新组 mutate(grp = cumsum(year != lag(year, default = first(year) - 1) + 1)) %>% group_by(country, grp) %>% summarize(start_year = min(year), end_year = max(year), .groups = "drop") %>% select(country, start_year, end_year) # 2. 生成所有可能的连续年份区间(基于全局年份范围) all_years <- sort(unique(df$year)) possible_intervals <- expand.grid(start = all_years, end = all_years) %>% filter(start <= end) %>% mutate(length = end - start + 1) # 3. 统计每个区间内满足全程无缺失的国家数 interval_country_count <- possible_intervals %>% rowwise() %>% mutate( # 找出所有国家中,其连续区间完全包含当前区间的 country_n = sum( country_continuous_intervals$start_year <= start & country_continuous_intervals$end_year >= end ) ) %>% ungroup() # 4. 选出最优区间:先按长度降序,再按国家数降序 optimal_interval <- interval_country_count %>% arrange(desc(length), desc(country_n)) %>% slice(1) # 5. 筛选对应区间和国家的数据 # 先找出符合条件的国家 qualified_countries <- country_continuous_intervals %>% filter(start_year <= optimal_interval$start & end_year >= optimal_interval$end) %>% pull(country) # 再筛选数据 balanced_max_years <- df %>% filter(country %in% qualified_countries, year >= optimal_interval$start, year <= optimal_interval$end, !is.na(x)) # 查看结果 balanced_max_years %>% summarize( start_year = min(year), end_year = max(year), total_years = n_distinct(year), country_count = n_distinct(country) )
结果说明
示例中会得到2002-2003年的区间,覆盖6个国家,符合预期。
生成带缺失值的面板数据代码
set.seed(0) # 保证结果可复现 # 创建10个国家、5年的面板框架 countries <- paste("Country", 1:10, sep="") years <- 2001:2005 df <- expand.grid(country = countries, year = years) # 生成随机数据 df$x <- rnorm(nrow(df)) # 为每个国家随机引入1-2个缺失年份 for (country in countries) { missing_years_count <- sample(1:2, 1, replace = TRUE) missing_years <- sample(years, missing_years_count) df$x[df$country == country & df$year %in% missing_years] <- NA } # 排序数据 df <- df %>% arrange(country, year) # 可视化缺失值 panelview(data = df, Y = "x", type = "missing", index = c("country", "year"))
内容的提问来源于stack exchange,提问作者flxflks
相关产品推荐
相关产品推荐

