如何在R中重塑含大量NA的Data Frame:按ID合并观测
解决思路与代码实现
先构造测试数据方便复现:
df <- data.frame( id = c(1,1,2,2,2,3,3), var1 = c(NA, 0.8, 0.7, NA, NA, NA, NA), var2 = c(0.4, NA, NA, 0.5, NA, 0.5, NA), var3 = c(NA, NA, NA, NA, 0.1, NA, 0.2) )
方法一:dplyr 分组汇总
按id分组后,对每个变量提取唯一的非NA值。因为每个id下每个变量仅一个有效值,用max()(带na.rm=TRUE)或first(na.rm=TRUE)均可:
library(dplyr) df_cleaned <- df %>% group_by(id) %>% summarize( var1 = if(all(is.na(var1))) NA else max(var1, na.rm = TRUE), var2 = if(all(is.na(var2))) NA else max(var2, na.rm = TRUE), var3 = if(all(is.na(var3))) NA else max(var3, na.rm = TRUE), .groups = "drop" )
注:加if(all(is.na(...)))是为了避免全NA变量返回-Inf,保证结果用NA填充。
方法二:data.table 高效处理
用data.table按id分组,直接提取每个变量的非NA值:
library(data.table) setDT(df) df_cleaned <- df[, lapply(.SD, function(x) x[!is.na(x)]), by = id]
每个变量每个id仅一个非NA值,lapply会自动提取并补全长度,得到目标格式。
方法三:tidyr pivot_wider 正确用法
你之前可能未设置values_fn参数,正确写法如下:
library(tidyr) # 先转长格式过滤NA,再转回宽格式 df_long <- df %>% pivot_longer(cols = starts_with("var"), names_to = "variable", values_to = "value", values_drop_na = TRUE) df_cleaned <- df_long %>% pivot_wider(names_from = "variable", values_from = "value")
也可一步完成:
df_cleaned <- df %>% pivot_wider( id_cols = id, names_from = everything(), values_from = starts_with("var"), values_fn = function(x) x[!is.na(x)], values_fill = NA )
三种方法均可得到你需要的输出结果。
内容的提问来源于stack exchange,提问作者lfgroene
相关产品推荐
相关产品推荐

