如何在一个大型数据框中,基于两列完全相同的值进行去重,并将剩余的列合并成一行?
示例数据:
ID<-c("A","A","A","A","A","A","B","B","B")
HFAdmission<-c("2020-01-01", "2020-02-01", "2020-03-01", NA, NA, NA, "2020-06-01", "2020-07-01", NA)
link_type<-c("Linked", "HF only", "HF only", "HES only", "HES only", "HES only", "Linked", "HF only", "HES only")
ADMIDATE<-c(NA,NA,NA,"2020-03-01","2020-04-01","2020-05-01",NA,NA, "2020-07-01")
newdate<-c(NA, "2020-02-01", "2020-03-01", "2020-03-01","2020-04-01","2020-05-01", NA, "2020-07-01", "2020-07-01")
df<-data.frame(ID, HFAdmission,link_type,ADMIDATE,newdate)
as.Date(df$HFAdmission)
as.Date(df$ADMIDATE)
as.Date(df$newdate)
df应该如下所示:
ID HFAdmission link_type ADMIDATE newdate
1 A 2020-01-01 Linked <NA> <NA>
2 A 2020-02-01 HF only <NA> 2020-02-01
3 A 2020-03-01 HF only <NA> 2020-03-01
4 A <NA> HES only 2020-03-01 2020-03-01
5 A <NA> HES only 2020-04-01 2020-04-01
6 A <NA> HES only 2020-05-01 2020-05-01
7 B 2020-06-01 Linked <NA> <NA>
8 B 2020-07-01 HF only <NA> 2020-07-01
9 B <NA> HES only 2020-07-01 2020-07-01
我希望基于两列(ID和 newdate)进行去重。
例如,设ID为 A,在第3 行和第4 行的newdate存在重复。
新创建的行在可能的情况下不会包含NA,因为来自第3 行的HFAdmission日期会被保留,而不是第4 行HDAdmission中的NA;同样来自第4 行的ADMIDATE日期将被保留,而不是第3 行的ADMIDATE中的NA。
当某列中存在两个非NA值时(例如link_type),该列应保留重复中的第一个非缺失值。
同样的情况也适用于第8 行和第9 行的重复。
去重并合并后的期望结果(第4 行和第9 行)如下:
ID HFAdmission link_type ADMIDATE newdate
1 A 2020-01-01 Linked <NA> <NA>
2 A 2020-02-01 HF only <NA> 2020-02-01
3 A 2020-03-01 HF only 2020-03-01 2020-03-01
4 A <NA> HES only 2020-04-01 2020-04-01
5 A <NA> HES only 2020-05-01 2020-05-01
6 B 2020-06-01 Linked <NA> <NA>
7 B 2020-07-01 HF only 2020-07-01 2020-07-01
我的数据集很大(一个5GB的 CSV文件),因此我一直在尝试使用基础R 函数,包括duplicated和 aggregate,但都没有成功。
解决方案
由于问题强调性能,我认为这里应避免直接的split-apply-combine方法(也就是把数据框按唯一的 ID 和 newdate 的组合拆分成组,在每个组中取每列的第一个非缺失值,然后再拼接)。若存在大量这样的分组,下面这种基于连接的解法在速度上会更快,同时内存占用也应保持在一个可接受的范围内。
First, create a new data frame df_new with the deduplicated value pairs of ID and newdate.
Then, for each of the other columns, add a new column to df_new containing the first non-missing value at each value pair, by:
- 删除
NAs - 在
ID和newdate上进行连接,只选择首次遇到的匹配项。
library(data.table)
setDT(df)
unique_cols <- c("ID", "newdate")
df_new <- df[, unique(.SD), .SDcols=unique_cols]
for (col in setdiff(names(df), unique_cols)) {
env <- list(v=col)
x <- df[!is.na(v), .SD, .SDcols=c(unique_cols, col), env=env]
df_new[[col]] <- x[df_new, on=unique_cols, mult="first", v, env=env]
}
setDF(df_new)
df_new
#> 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
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。