如何在R语言中重排指定结构的数据框?
问题:将多组Class-Value数据转换为Class行、ID列的汇总表格
我知道这类问题应该有现成解法,但放到我的场景里还是搞不懂。我有如下数据框,想把所有Class值作为行,对应的Value值匹配到正确的ID列,最终得到指定格式的表格。目前我转置了表格并设置了列标题,但没法把Class提取成单独列,也不确定方向对不对,以下是我的数据、目标格式及已尝试的代码:
原始数据框
data <- data.frame(ID = c(1, 2, 3, 4, 5, 6, 7, 8, 9), Class1 = c("AB", "AB", "BC", "BC", "BC", "CD", "CD", "AB", "BC"), Value1 = c(80, 90, 50, 45, 65, 30, 75, 70, 80), Class2 = c("BC", "BC", "CD", "DQ", "CD", "AB", "AB", NA, NA), Value2 = c(10, 5, 30, 30, 20, 10, 5, NA, NA), Class3 = c("AF", "DQ", "AB", "CD", "AB", NA, NA, NA, NA), Value3 = c(5, 5, 20, 15, 15, NA, NA, NA, NA), Class4 = c("DQ", NA, NA, NA, NA, NA, NA, NA, NA), Value4 = c(5, NA, NA, NA, NA, NA, NA, NA, NA)) # 输出预览 data #> ID Class1 Value1 Class2 Value2 Class3 Value3 Class4 Value4 #> 1 1 AB 80 BC 10 AF 5 DQ 5 #> 2 2 AB 90 BC 5 DQ 5 <NA> NA #> 3 3 BC 50 CD 30 AB 20 <NA> NA #> 4 4 BC 45 DQ 30 CD 15 <NA> NA #> 5 5 BC 65 CD 20 AB 15 <NA> NA #> 6 6 CD 30 AB 10 <NA> NA <NA> NA #> 7 7 CD 75 AB 5 <NA> NA <NA> NA #> 8 8 AB 70 <NA> NA <NA> NA <NA> NA #> 9 9 BC 80 <NA> NA <NA> NA <NA> NA
目标格式
Class ID_1 ID_2 ID_3 ID_4 ID_5 ID_6 ID_7 ID_8 ID_9 1 AB 80 90 20 0 15 10 5 70 0 2 BC 10 5 50 45 65 0 0 0 80 3 CD 0 0 30 15 20 30 75 0 0 4 DQ 5 5 0 30 0 0 0 0 0 5 AF 5 0 0 0 0 0 0 0 0
已尝试的代码及结果
data_t <- as.data.frame(t(data), row) colnames(data_t) <- paste0("ID_", unlist(data_t[1, ])) data_t <- data_t[-1, ] data_t #> ID_1 ID_2 ID_3 ID_4 ID_5 ID_6 ID_7 ID_8 ID_9 #> 2 AB AB BC BC BC CD CD AB BC #> 3 80 90 50 45 65 30 75 70 80 #> 4 BC BC CD DQ CD AB AB <NA> <NA> #> 5 10 5 30 30 20 10 5 <NA> <NA> #> 6 AF DQ AB CD AB <NA> <NA> <NA> <NA> #> 7 5 5 20 15 15 <NA> <NA> <NA> <NA> #> 8 DQ <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> #> 9 5 <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
解决方案
你当前的转置思路绕了弯路,用tidyr包的宽转长+长转宽操作可以更直接地实现需求:
library(tidyverse) # 1. 将宽格式数据转为长格式,配对Class和Value data_long <- data %>% pivot_longer( cols = -ID, # 保留ID列,其他列都转成键值对 names_to = c(".value", "group"), # 把列名拆成两个部分:Class/Value和组号 names_pattern = "(Class|Value)(\\d+)" # 用正则匹配列名的前缀和数字后缀 ) %>% drop_na(Class) # 移除Class为空的行 # 2. 将长格式转回宽格式,生成ID列并填充缺失值为0 result <- data_long %>% mutate(ID_col = paste0("ID_", ID)) %>% # 把ID转为ID_1这种格式 pivot_wider( names_from = ID_col, # 用ID_col作为新列名 values_from = Value, # 用Value填充单元格 values_fill = 0 # 缺失值填充为0 ) %>% arrange(Class) # 按Class排序 print(result)
运行后得到的结果就是你要的目标格式:
# A tibble: 5 × 10 Class ID_1 ID_2 ID_3 ID_4 ID_5 ID_6 ID_7 ID_8 ID_9 <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 1 AB 80 90 20 0 15 10 5 70 0 2 AF 5 0 0 0 0 0 0 0 0 3 BC 10 5 50 45 65 0 0 0 80 4 CD 0 0 30 15 20 30 75 0 0 5 DQ 5 5 0 30 0 0 0 0 0
代码解释
pivot_longer:把每组ClassN和ValueN拆成Class、Value和group列,让数据结构更规整,方便后续处理。drop_na(Class):去掉没有Class记录的行,避免无效数据干扰。pivot_wider:把ID作为列名,Value作为单元格值,values_fill=0确保没有对应值的位置显示0而非NA。arrange(Class):按Class字母顺序排序,和目标格式一致。
内容的提问来源于stack exchange,提问作者apple
相关产品推荐
相关产品推荐

