我已经搜索了几个小时。这应该很容易,但我看不出如何:(
我有一个名为 ds 的数据帧,其中包含一个结构如下的列:
name
"Doe, Mr. John"
"Worth, Miss. Jane"
我想提取中间词并将其放入新列中。
#This is how I'm doing it now
ds$title <- NA
mr <- grep(", Mr. ", ds$name)
miss <- grep(", Miss. ", ds$name)
ds$title[mr] <- ", Mr. "
ds$title[miss] <- ", Miss. "
我正在尝试用正则表达式对此进行概括,以便它采用与"逗号空格单词周期空间"模式匹配的任何中间词
这是我最好的猜测,但它只会删除模式:
gsub(", .+\.+ ", "", ds$name)
如何保留模式并删除其余部分?
谢谢!
可以使用捕获组。 基本上,您匹配整个模式,使用捕获组匹配要保留的部分,并将整个匹配替换为捕获组:
# I often specify perl = TRUE, though it isn't necessary here
(ds$title <- gsub(".+(, .+\.+ ).+", "\1", ds$name, perl = TRUE))
#[1] ", Mr. " ", Miss. "
捕获组是括号中的内容 ( (, .+\.+ )
),您可以使用 \1
引用它。 如果您有第二个捕获组,则将其称为 \2
。
单词,句点,空格,则可以将捕获组修改为(, .+\. )
。 您只需要匹配一个周期,而不是一个或多个周期。
不使用捕获组的简单stringi
替代方法是stri_extract_first_regex
(或者在这种情况下stri_extract_last_regex
或stri_extract_all_regex
正常工作)
library(stringi)
ds$title <- stri_extract_first_regex(ds$name, ", .+\. ")
#[1] ", Mr. " ", Miss. "
正如thelatemail在评论中指出的那样,您也可以使用base R做类似的事情,但是记住如何使用regmatches
和regexpr
函数有点困难:
regmatches(ds$name, regexpr(", .+\. ", ds$name))
#[1] ", Mr. " ", Miss. "
匹配的捕获组是您的 BFF:
library(stringi)
library(purrr)
ds <- data.frame(name=c("Doe, Mr. John", "Worth, Miss. Jane"), stringsAsFactors=FALSE)
nonsp <- "[[:alnum:][:punct:]]+"
sp <- "[[:blank:]]+"
stri_match_all_regex(ds$name, nonsp %s+% sp %s+% "(" %s+% nonsp %s+% ")" %s+% sp %s+% nonsp) %>%
map_chr(2)
## [1] "Mr." "Miss."
对于"向数据框添加列"的需求:
library(stringi)
library(dplyr)
library(purrr)
ds <- data.frame(name=c("Doe, Mr. John", "Worth, Miss. Jane"), stringsAsFactors=FALSE)
nonsp <- "[[:alnum:][:punct:]]+"
sp <- "[[:blank:]]+"
mutate(ds, title=stri_match_all_regex(ds$name, nonsp %s+% sp %s+% "(" %s+% nonsp %s+% ")" %s+% sp %s+% nonsp) %>% map_chr(2))
## name title
## 1 Doe, Mr. John Mr.
## 2 Worth, Miss. Jane Miss.