如何使用pivot_longer直接提取前缀实现宽表转长表
问题
我的数据常以宽表格式呈现,列名包含"Left/Right"或"Pre/Post"前缀但无分隔符,需要按这些前缀合并变量转成长表。目前我通过gsub()在列名中插入分隔符,再用pivot_longer的names_sep参数实现转换,但想知道是否可以直接使用pivot_longer的names_prefix、names_pattern、names_to语法完成。
示例宽表:
HW <- tribble( ~Subject, ~LeftV1, ~RightV1, ~LeftV2, ~RightV2, ~LeftV3, ~RightV3, "A", 0, 1, 10, 11, 100, 101, "B", 2, 3, 12, 13, 102, 103, "C", 4, 5, 14, 15, 104, 105)
期望得到的长表结构:
HWT <- tribble( ~Subject, ~Side, ~V1, ~V2, ~V3, "A", "Left", 0, 10, 100, "A", "Right", 1, 11, 101, "B", "Left", 2, 12, 102, "B", "Right", 3, 13, 103, "C", "Left", 4, 14, 104, "C", "Right", 5, 15, 105)
我尝试了如下语法,但均出现语法错误:
HWT <- HW %>% pivot_longer( cols = contains(c("Left", "Right")), names_pattern = "/^(Left|Right)", names_to = c('Side', '.value') )
或:
HWT <- HW %>% pivot_longer( cols = contains(c("Left", "Right")), names_prefix = "/^(Left|Right)", names_to = c('Side', '.value') )
解决方案
你之前的写法问题出在正则表达式格式和参数使用逻辑上:
names_pattern不需要额外添加开头的/,且必须完整匹配列名的两个组成部分(前缀+变量名),通过捕获组分别对应names_to中的元素;names_prefix仅用于移除指定前缀,无法同时提取分组信息,不适合当前场景。
正确的写法是用names_pattern分别捕获前缀(Left/Right)和后续变量名(V1/V2/V3),再通过names_to指定第一个捕获组映射到Side列,第二个捕获组对应.value(即保留变量名作为新的列名):
library(tidyr) library(dplyr) HWT <- HW %>% pivot_longer( cols = -Subject, # 排除Subject列,用contains(c("Left", "Right"))也可 names_pattern = "(Left|Right)(V\\d+)", names_to = c("Side", ".value") )
运行这段代码即可得到期望的长表结构。如果处理"Pre/Post"前缀的场景,只需将正则中的(Left|Right)替换为(Pre|Post)即可。
内容的提问来源于stack exchange,提问作者bmacwilliams
相关产品推荐
相关产品推荐

