面板数据集重复值与错误值检测的简便方法探讨
数据问题检测方案
1. 检测完全重复行
用janitor包的get_dupes()函数可快速定位所有重复行,直观展示重复分组与具体行内容:
library(janitor) get_dupes(df1)
也可使用基础函数标记重复行:
library(dplyr) df1 %>% mutate(is_duplicate = duplicated(.)) %>% filter(is_duplicate)
2. 检测分组内的数值冲突
按City和Year分组,统计每个数值列的不同值数量,若数量大于1则说明该组存在数值冲突:
df1 %>% group_by(City, Year) %>% summarize( across( c(Burger_cost, Cola_cost, Resident_AVGGrowth_cm), ~n_distinct(., na.rm = TRUE) ), row_count = n() ) %>% filter(if_any(c(Burger_cost, Cola_cost, Resident_AVGGrowth_cm), ~. >1) | row_count >1)
运行后会直接筛选出存在问题的分组(如纽约2018年、纽约2020年)。
3. 检测数值异常值
针对居民身高列,用范围筛选找出不符合50-400cm规则的异常行:
df1 %>% filter(Resident_AVGGrowth_cm <50 | Resident_AVGGrowth_cm >400)
数据问题处理方案
1. 删除完全重复行
用distinct()直接去重,保留每组唯一行:
df_clean <- df1 %>% distinct()
这一步会自动删除伦敦的全量重复行,以及阿布扎比2018-2020年的重复行。
2. 过滤异常值
保留身高在50-400cm范围内的行:
df_clean <- df_clean %>% filter(between(Resident_AVGGrowth_cm, 50, 400))
这一步会移除纽约2020年身高500cm的异常行。
3. 处理需人工确认的数值冲突
先提取所有存在冲突的分组行,导出供人工核对:
conflict_records <- df_clean %>% group_by(City, Year) %>% filter(n() >1 | if_any(c(Burger_cost, Cola_cost, Resident_AVGGrowth_cm), ~n_distinct(., na.rm=TRUE)>1)) %>% ungroup() # 导出到CSV方便人工核对 write.csv(conflict_records, "conflict_records.csv", row.names = FALSE)
人工确认后,将正确的行替换回数据集:
# 假设人工确认纽约2018年汉堡价格应为3,保留对应行 confirmed_records <- conflict_records %>% filter(City == "New York", Year ==2018, Burger_cost ==3) # 合并无冲突行和确认后的行 df_final <- df_clean %>% anti_join(conflict_records, by = c("City", "Year")) %>% bind_rows(confirmed_records)
可选:处理缺失值
阿布扎比2017年的可乐价格为NA,若需补全可根据需求选择方法:
# 用同城市其他年份的平均值填充 df_final <- df_final %>% group_by(City) %>% mutate(Cola_cost = replace_na(Cola_cost, mean(Cola_cost, na.rm=TRUE))) %>% ungroup()
内容的提问来源于stack exchange,提问作者Alexander Shemetev
相关产品推荐
相关产品推荐

