我有一个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:
^([^ ]*)
但是这将选择第一个空间和之前的一切。但是你如何只选择第一个空间呢?
假设第一个非空白块不是太大的值,您可以利用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
列表的第二列值)。这是另一种变化。它将数字拉出列,然后在第一列中删除它。这里的一个优点是拉出的数字是类数字(你总是可以用其他方法从字符转换)。
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)。
关于所需的确切输出的问题并不具体,因此假设输出应该是两列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)
请注意,在tidyr中有一个open issue #397,如果实现它会将上面的内容减少到以下代码。 (更新:tidyr 0.8.2现在实现此功能)
DF %>%
separate(X, into = c(NA, "X", "Y"),
extra = "merge", convert = TRUE, remove = TRUE)
可重复输入的输入:
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))