如何将长格式数据转为宽格式并以零填充缺失值
区分原生NA与转换新增NA的宽格式转换方案
要实现仅将转换时新增的NA(因ID-region组合不存在而生成的缺失)替换为0,同时保留长格式中原有的NA,可以按以下两种方式处理:
方法一:Base R 分步实现
- 生成所有ID与region的完整组合,避免转换时出现缺失:
# 提取唯一的ID和region值 all_ids <- unique(df$ID) all_regions <- unique(df$region) # 创建包含所有组合的空数据框 full_comb <- expand.grid(ID = all_ids, region = all_regions, stringsAsFactors = FALSE)
- 左连接原数据,保留原生NA,新增组合会生成NA:
full_df <- merge(full_comb, df, by = c("ID", "region"), all.x = TRUE)
- 标记并替换新增的NA:
# 提取原数据中已存在的ID-region组合 existing_pairs <- paste(df$ID, df$region, sep = "_") # 标记哪些是转换时新增的组合 full_df$is_new <- !paste(full_df$ID, full_df$region, sep = "_") %in% existing_pairs # 仅将新增组合的NA替换为0,原生NA保持不变 full_df$status[full_df$is_new & is.na(full_df$status)] <- 0
- 转换为宽格式:
wide_df <- reshape(full_df[, c("ID", "region", "status")], idvar = "ID", timevar = "region", direction = "wide")
方法二:Tidyverse 简洁实现
借助tidyr的complete函数补全组合,再精准替换NA:
library(tidyverse) wide_df <- df %>% # 补全所有ID-region组合,补全行的status会默认设为NA complete(ID, region) %>% # 标记新增组合 mutate(is_new = !paste(ID, region, sep = "_") %in% paste(df$ID, df$region, sep = "_")) %>% # 替换新增组合的NA为0,原生NA保留 mutate(status = ifelse(is_new & is.na(status), 0, status)) %>% # 转换为宽格式 pivot_wider(names_from = region, values_from = status, names_prefix = "status.")
最终结果
两种方法都会得到如下宽格式数据,其中:
- ID=1的
status.B保留原长格式的NA - ID=3的
status.B被替换为0(转换时新增的缺失)
ID status.A status.B 1 1 1 NA 2 2 1 1 3 3 NA 0
内容的提问来源于stack exchange,提问作者Caterina
相关产品推荐
相关产品推荐

