如何在R中使用正则表达式查找句子中的第一个空格

问题描述 投票:3回答:3

我有一个data.frame,其中包含一个列如下的值:

[2] wererea 187w 50HH (1)
[3] werewefrea 145y 50HH (4)
[5] weredssda 100NH (2)

我想将此列分成两列,分离应在第一个空格处完成。我现在如何在]的帮助下这样做:

DF <- separate(DF , "X", into = c("X","Y"), sep = "\\] ", remove = TRUE)
DF$X<- gsub("\\[", "", DF$X)

选择最后一个空格的方法如下:

DF <- separate(DF, "X", into = c("X","Y"), sep = " (?=[^ ]*$)", remove = TRUE)

我找到了这个RegEx:

^([^ ]*) 

但是这将选择第一个空间和之前的一切。但是你如何只选择第一个空间呢?

r regex tidyr
3个回答
3
投票

假设第一个非空白块不是太大的值,您可以利用ICU约束宽度lookbehind(即在某种程度上允许{n,m}量词)。比如说,如果字符串start处的空格字符数达到1000,这将有效:

separate(DF, "X", into = c("X","Y"), sep = "(?<=^\\S{0,1000})\\s+", remove = TRUE)

(?<=^\\S{0,1000})\\s+模式将匹配1个空格,前面是字符串的开头,后跟0到1000个非空白字符。

否则,你可以使用tidyr::extract

library(tidyr)
DF %>%
    extract(col="X", into = c("X","Y"), regex="^(\\S+)\\s+(.*)")

如果你想避开一个数字周围的第一个[...],使用一个小的变化:

extract(col="X", into = c("X","Y"), regex="^\\[(\\d+)]\\s+(.*)")

^(\\S+)\\s+(.*)正则表达式匹配

  • ^ - 字符串的开头
  • (\\S+) - 捕获组1:一个或多个非空白字符(它将是into列表中的第一列值)(在另一种模式中,(\\d+)将捕获1个或多个数字)
  • \\s+ - 1+空格
  • (.*) - 捕获第2组:任何一个或多个字符(它将是来自into列表的第二列值)。

0
投票

这是另一种变化。它将数字拉出列,然后在第一列中删除它。这里的一个优点是拉出的数字是类数字(你总是可以用其他方法从字符转换)。

library(tidyverse)

df %>% 
  mutate(Y = parse_number(X),
         X = gsub("\\[.*\\]", "", X))
#>                           X Y
#> 1     wererea 187w 50HH (1) 2
#> 2  werewefrea 145y 50HH (4) 3
#> 3       weredssda 100NH (2) 5

reprex package创建于2018-09-20(v0.2.0)。


0
投票

关于所需的确切输出的问题并不具体,因此假设输出应该是两列X和Y,使得第一列是数字行号,第二列是将行与行分隔开的空格后面的文本数。在这种情况下,如果之后删除了垃圾,separate使用的默认正则表达式应该没问题:

library(dplyr)
library(tidyr)

DF %>%
  separate(X, into = c("junk", "X", "Y"), 
    extra = "merge", convert = TRUE, remove = TRUE) %>%
  select(-junk)

赠送:

  X                        Y
1 2    wererea 187w 50HH (1)
2 3 werewefrea 145y 50HH (4)
3 5      weredssda 100NH (2)

替代

之后删除垃圾的另一种方法是删除[之前:

DF %>%
  mutate(X = sub(".", "", X)) %>%
  separate(X, into = c("X", "Y"), 
     extra = "merge", convert = TRUE, remove = TRUE)
##   X                        Y
## 1 2    wererea 187w 50HH (1)
## 2 3 werewefrea 145y 50HH (4)
## 3 5      weredssda 100NH (2)

注1

请注意,在tidyr中有一个open issue #397,如果实现它会将上面的内容减少到以下代码。 (更新:tidyr 0.8.2现在实现此功能)

DF %>%
  separate(X, into = c(NA, "X", "Y"), 
    extra = "merge", convert = TRUE, remove = TRUE)

笔记2

可重复输入的输入:

DF <-
structure(list(X = c("[2] wererea 187w 50HH (1)", "[3] werewefrea 145y 50HH (4)", 
"[5] weredssda 100NH (2)")), class = "data.frame", row.names = c(NA, 
-3L))
© www.soinside.com 2019 - 2024. All rights reserved.