如何用pivot_longer将列重构为含两个对应值列的行?
问题描述
现有如下格式的数据:
location group financial_year h0to2 h10plus h2to4 h4to10 total perc0to2 perc2to4 perc4to10 <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 6 partnership x 2020/21 0 5 5 15 25 0 20 60
需要生成新列level_of_service,取值为"a0to2"、"a2to4"、"a4to10"、"a10+",同时生成Value列提取以h开头列的数值,Percentage列提取以perc开头列的数值。
此前使用的pivot_longer代码将h和perc列都转为level_of_service行,每行仅对应一个值:
mydata2 <- mydata %>% pivot_longer(cols = c("h0to2", "h2to4", "h4to10", "h10plus", "perc0to2", "perc2to4", "perc4to10", "perc10plus"), names_to = "level_of_service" )
得到的结果如下:
location group financial_year total level_of_service value <chr> <chr> <chr> <dbl> <chr> <dbl> 1 partnership x 2020/21 0 h0to2 0 2 partnership x 2020/21 0 perc0to2 0
需要调整结果为包含Value和Percentage两个值列,分别对应h开头列和perc开头列的数值。
解决方案
可以借助pivot_longer的names_to和names_pattern参数拆分列名,将前缀(h/perc)映射为值列,同时提取服务等级信息,再调整成目标格式:
library(dplyr) library(tidyr) mydata2 <- mydata %>% pivot_longer( # 匹配所有以h或perc开头的列 cols = starts_with(c("h", "perc")), # .value表示把前缀作为值列的名称,level_code存储拆分后的等级部分 names_to = c(".value", "level_code"), # 正则表达式拆分列名:捕获组1是h/perc,捕获组2是后面的等级字符串 names_pattern = "(h|perc)(.*)" ) %>% # 重命名值列为目标名称 rename( Value = h, Percentage = perc ) %>% # 将level_code转换为目标level_of_service取值 mutate( level_of_service = case_when( level_code == "0to2" ~ "a0to2", level_code == "2to4" ~ "a2to4", level_code == "4to10" ~ "a4to10", level_code == "10plus" ~ "a10+" ) ) %>% # 移除临时的level_code列 select(-level_code)
执行后得到的结果示例:
location group financial_year total Value Percentage level_of_service <chr> <chr> <chr> <dbl> <dbl> <dbl> <chr> 1 partnership x 2020/21 25 0 0 a0to2 2 partnership x 2020/21 25 5 NA a10+ 3 partnership x 2020/21 25 5 20 a2to4 4 partnership x 2020/21 25 15 60 a4to10
注意:如果原数据中没有perc10plus列,Percentage对应a10+的位置会显示NA,可根据实际需求用replace_na(Percentage, 0)这类代码补充缺失值。
内容的提问来源于stack exchange,提问作者Mark Durkan
相关产品推荐
相关产品推荐

