列名包含两部分的tibble如何转长格式?可通过dplyr实现吗?
你要的效果用pivot_longer可以一行核心代码实现,你之前调试没成功大概率是没配好列名拆分和排序规则,具体实现如下:
你已经加载了tidyverse,其中pivot_longer属于tidyr包,和dplyr同属tidyverse生态,可以直接调用,完整代码:
library(tidyverse) df = tribble( ~id, ~a1, ~a2, ~a3, ~b1, ~b2, ~b3, ~c1, ~c2, ~c3, 1, 1, 4, 7, 11, 14, 17, 21, 24, 27, 2, 2, 5, 8, 12, 15, 18, 22, 25, 28, 3, 3, 6, 8, 13, 16, 19, 23, 26, 29, ) df_long <- df %>% pivot_longer( cols = -id, # 除了id列,其余所有列都转长格式 names_to = c("name", "nr"), # 原列名拆分后存为name和nr两列 names_sep = 1, # 拆分规则:在第1个字符后切割,刚好把a1拆为"a"和"1" values_to = "data", # 原单元格的值存在data列 cols_vary = "slowest" # 控制排序规则,优先按name、nr排序,再按id排序,和你给的示例输出顺序完全一致 ) %>% mutate(nr = as.integer(nr)) # 把nr列从字符串转为整数,和示例格式匹配
运行后得到的df_long和你给出的预期输出完全一致。
如果你确实需要仅用dplyr原生函数实现(不依赖tidyr),也可以用如下写法,不过逻辑会繁琐很多:
df_long <- df %>% rowwise() %>% reframe( id = id, name = rep(c("a","b","c"), each = 3), nr = rep(1:3, 3), data = c(a1,a2,a3,b1,b2,b3,c1,c2,c3) )
两种方法都可以得到你要的结果,优先推荐第一种更简洁的pivot_longer写法。
内容的提问来源于stack exchange,提问作者blrun
相关产品推荐
相关产品推荐

