如何将含(%)与不含(%)的行转换为多列(R数据框处理)
解决R数据框中百分比成对行转列的问题
需求说明
需要将原数据框中A列里共享主体名称、仅后缀(%)不同的成对行,合并为一行,拆分出原值和百分比值对应的列,最终结构包含主体名、原值、带(%)的名称、百分比值这几列。
处理步骤与代码
首先加载原数据:
df <- structure(list(Z = c("51", "51", "51", "51", "51", "51", "51", "51", "60", "60", "60", "60", "60", "60", "60", "60"), A = c("Unp", "Dip", "Dit", "Tip", "Unp (%)", "Dip (%)", "Dit (%)", "Tip (%)", "Unp", "Dip", "Dit", "Tip", "Unp (%)", "Dip (%)", "Dit (%)", "Tip (%)"), B = c(74, 190, 120, 284, 150, 147.222222222222, 101.39, 125, 74, 179, 112, 265, 150, 139.583333333333, 106.94, 118.91)), row.names = c(NA, -16L), class = c("tbl_df", "tbl", "data.frame"))
使用tidyverse工具包处理:
library(tidyverse) # 处理数据,合并成对行 df_result <- df %>% # 提取主体类别,标记是否为百分比行 mutate( category = str_remove(A, " \\(\\%\\)"), # 去掉"(%)"后缀得到主体名 is_percent = str_detect(A, "\\(\\%\\)") # 判断是否是百分比行 ) %>% # 按分组键(Z和主体类别)合并行 group_by(Z, category) %>% summarise( var1 = first(category), # 主体名称列 var2 = B[!is_percent], # 原值列 var3 = first(A[is_percent]), # 带(%)的名称列 var4 = B[is_percent], # 百分比值列 .groups = "drop" # 取消分组 ) # 查看结果 print(df_result)
结果说明
运行后得到的df_result核心结构如下(以Z=51的部分为例):
# A tibble: 8 × 6 Z category var1 var2 var3 var4 <chr> <chr> <chr> <dbl> <chr> <dbl> 1 51 Dip Dip 190 Dip (%) 147. 2 51 Dit Dit 120 Dit (%) 101. 3 51 Tip Tip 284 Tip (%) 125 4 51 Unp Unp 74 Unp (%) 150
如果不需要Z和category列,可以用select(-Z, -category)移除。
补充:base R实现方式
如果不想依赖tidyverse,可以用base R的reshape函数:
# 提取主体类别和类型 df$category <- gsub(" \\(\\%\\)", "", df$A) df$type <- ifelse(grepl("\\(\\%\\)", df$A), "percent", "value") # 转宽表 df_result_base <- reshape(df, idvar = c("Z", "category"), timevar = "type", direction = "wide") # 重命名列名匹配需求 names(df_result_base) <- c("Z", "var1", "var2", "var4") df_result_base$var3 <- paste0(df_result_base$var1, " (%)") # 调整列顺序 df_result_base <- df_result_base[, c("var1", "var2", "var3", "var4", "Z")]
内容的提问来源于stack exchange,提问作者12666727b9
相关产品推荐
相关产品推荐

