如何按+或-的最后出现位置拆分R数据框的两列
按+/-最后出现位置拆分数据框列的解决方案
问题背景
需要按+或-符号的最后出现位置,在符号紧邻的前方拆分数据框的两列。现有测试数据:
zed = data.frame( value = c('+23-25', '-23.5+25.5', '-24+24', '-3-6'), label = c('p34-150', 'p 243-130', 'p215 +115', 'p215 +115'), stringsAsFactors = FALSE )
期望得到的拆分结果:
output = data.frame( value1 = c('+23', '-23.5', '-24', '-3'), value2 = c('-25', '+25.5', '+24', '-6'), label1 = c('p34', 'p 243', 'p215', 'p215'), label2 = c('-150', '-130', '+115', '+115'), stringsAsFactors = FALSE )
此前尝试的方案均失效:
separate(value, into = c("value1", "value2"), sep = "+|-"):+|-属于非法正则表达式"(?=[+-][^+-]*$)[+-]":返回空列,未达到拆分效果
补充问题:特殊空格导致拆分失效
后续遇到非普通空格的情况,常规处理无法生效:
> zed$Total[1] [1] "O 239.5−110" > head(zed %>% separate(Total, into = c("label1", "label2"), sep = "(?=[\\+-][^\\+-]*$)"), 1) label1 label2 1 O 239.5−110 <NA> Warning message: Expected 2 pieces. Missing pieces filled with `NA` in 12 rows [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]. > gsub(' ', '', zed$Total[1]) [1] "O 239.5−110"
无法用gsub去除空格,导致separate()拆分失败。
解决方案
1. 基础拆分:正确的正则表达式
要精准匹配最后一个+或-并拆分,需使用负向回顾断言+正向先行断言组合的正则,同时注意转义和参数设置:
library(tidyr) # 拆分value列 zed <- zed %>% separate(value, into = c("value1", "value2"), sep = "(?=(?<![+-])[+-][^+-]*$)", extra = "merge") # 拆分label列 zed <- zed %>% separate(label, into = c("label1", "label2"), sep = "(?=(?<![+-])[+-][^+-]*$)", extra = "merge")
正则逻辑说明:
(?<![+-]):确保当前位置前不是+或-,避免匹配连续符号[+-]:匹配目标拆分符号[^+-]*$:保证符号后直到字符串结尾无其他+/-,锁定最后一个符号extra = "merge":强制只拆分为两部分,避免多余内容被丢弃
2. 处理特殊空格与特殊符号问题
从测试结果看,空格为非普通空白字符,需用匹配所有空白的正则处理;同时存在全角减号−的情况,需扩展匹配范围:
library(dplyr) library(tidyr) # 替换所有空白字符(包括全角空格、制表符等) zed <- zed %>% mutate(Total = gsub("\\s", "", Total)) # 适配全角/半角减号的拆分正则 zed <- zed %>% separate(Total, into = c("label1", "label2"), sep = "(?=(?<![+−-])[+−-][^+−-]*$)", extra = "merge")
内容的提问来源于stack exchange,提问作者Canovice
相关产品推荐
相关产品推荐

