如何对大型R DataFrame基于两列去重并合并非缺失值列
解决大型R DataFrame基于ID和newdate去重并合并非NA值的问题
问题描述
你有一个5GB的CSV导入的大型R DataFrame,需要基于ID和newdate两列去重,合并规则为:
- 重复行合并时优先保留非NA值
- 同一列存在多个非NA值时,保留第一个出现的取值
解决方案
针对大文件场景,推荐使用data.table(效率最优)或dplyr(语法直观)实现,以下是具体代码:
方法1:使用data.table(适合超大文件)
data.table的fread读取大文件速度远快于base R,分组汇总效率也更高:
# 加载data.table包 library(data.table) # 读取5GB CSV文件(自动处理大部分格式) df <- fread("your_large_file.csv") # 将日期列转换为Date类型(如果原始数据是字符格式) df[, c("HFAdmission", "ADMIDATE", "newdate") := lapply(.SD, as.Date), .SDcols = c("HFAdmission", "ADMIDATE", "newdate")] # 定义函数:返回向量中第一个非NA值,全NA则返回NA first_non_na <- function(x) { non_na_vals <- x[!is.na(x)] if (length(non_na_vals) > 0) non_na_vals[1] else NA } # 按ID和newdate分组,对每个列应用first_non_na函数 result <- df[, lapply(.SD, first_non_na), by = .(ID, newdate)] # 查看结果(和预期输出一致) print(result)
方法2:使用dplyr + readr(语法更易读)
readr的read_csv读取大文件效率优于base R的read.csv,dplyr的分组语法更直观:
# 加载所需包 library(dplyr) library(readr) # 读取大文件 df <- read_csv("your_large_file.csv") # 转换日期列 df <- df %>% mutate(across(c(HFAdmission, ADMIDATE, newdate), as.Date)) # 分组合并:按ID和newdate分组,每个列取第一个非NA值 result <- df %>% group_by(ID, newdate) %>% summarize( HFAdmission = first(na.omit(HFAdmission)) %||% NA_Date_, link_type = first(na.omit(link_type)) %||% NA_character_, ADMIDATE = first(na.omit(ADMIDATE)) %||% NA_Date_, .groups = "drop" # 取消分组状态 ) # 查看结果 print(result)
结果验证
用你的示例数据测试上述代码,会得到完全符合预期的输出:
ID newdate HFAdmission link_type ADMIDATE 1: A <NA> 2020-01-01 Linked <NA> 2: A 2020-02-01 2020-02-01 HF only <NA> 3: A 2020-03-01 2020-03-01 HF only 2020-03-01 4: A 2020-04-01 <NA> HES only 2020-04-01 5: A 2020-05-01 <NA> HES only 2020-05-01 6: B <NA> 2020-06-01 Linked <NA> 7: B 2020-07-01 2020-07-01 HF only 2020-07-01
为什么base R方法难以实现?
duplicated只能标记重复行,无法直接合并非NA值aggregate处理大文件效率极低,且默认函数无法灵活实现"取第一个非NA"的规则,容易丢失数据或不符合需求
内容的提问来源于stack exchange,提问作者Simran Parmar
相关产品推荐
相关产品推荐

