R语言按/和%*%分割字符串并生成data.frame的实现问题
我来帮你解决这个字符串分割的问题!先拆解你之前遇到的问题,再一步步给出正确的实现方法。
问题分析:你之前写法的核心问题
- 正则表达式逻辑错误:你用的
[/(%*%)]是字符类匹配,它只会单独匹配/、(、%、*、)这些单个字符,完全不是你想要的“提取被%包裹的符号”的逻辑。所以-不在这个字符类里,自然不会被识别;同时,当两个分割符相邻(比如%(),分割后就会产生空字符串。 - 整体思路偏差:直接用
strsplit把所有分割符拆开会混淆坐标点和符号的内容,没办法直接区分哪些是x/y、哪些是要存入z列的符号。
正确的实现思路
我们需要分开提取坐标点(x,y)和符号z,再把它们组合成目标data.frame:
- 提取所有
x / y格式的坐标对,拆分得到x和y; - 提取被
%包裹的符号(比如(、-、)); - 因为最后一个坐标点没有对应的符号,给z列补一个
NA; - 组合成最终的data.frame。
具体代码实现(两种方式)
方式一:Base R 原生函数实现
s <- "0 / 10 %(% 1 / 11 %-% 2 / 12 %)% 3 / 13" # 1. 提取所有x/y格式的字符串片段 xy_pairs <- regmatches(s, gregexpr("\\d+ / \\d+", s))[[1]] # 2. 拆分每个坐标对,得到x和y的数值 xy_split <- do.call(rbind, strsplit(xy_pairs, " / ")) x <- as.integer(xy_split[, 1]) y <- as.integer(xy_split[, 2]) # 3. 提取被%包裹的符号(用Perl正则的预查语法精准匹配%之间的内容) symbols <- regmatches(s, gregexpr("(?<=%)[^%]+(?=%)", s, perl = TRUE))[[1]] # 4. 给最后一个坐标补NA,组合成目标data.frame z <- c(symbols, NA) result <- data.frame(x = x, y = y, z = z, stringsAsFactors = FALSE) # 查看结果 print(result)
方式二:用stringr包更简洁实现
如果你习惯用stringr包(字符串处理更直观),可以这样写:
library(stringr) s <- "0 / 10 %(% 1 / 11 %-% 2 / 12 %)% 3 / 13" # 提取x:匹配" / "前面的数字 x <- str_extract_all(s, "\\d+(?= /)")[[1]] %>% as.integer() # 提取y:匹配" / "后面的数字 y <- str_extract_all(s, "(?<= / )\\d+")[[1]] %>% as.integer() # 提取%包裹的符号 z <- str_extract_all(s, "(?<=%)[^%]+(?=%)")[[1]] # 给最后一个坐标补NA z <- c(z, NA) # 生成结果 result <- data.frame(x, y, z, stringsAsFactors = FALSE) result
运行结果
两种方式都会输出你想要的结果:
x y z 1 0 10 ( 2 1 11 - 3 2 12 ) 4 3 13 <NA>
内容的提问来源于stack exchange,提问作者symbolrush
相关产品推荐
相关产品推荐

