处理多个 grepl 语句中的关系
Handling ties in multiple grepl statements
我正在做一项作业,需要清除大量混乱的字符串数据。
我已经解决了大多数问题,但遇到了两个问题:
- 使用多个 grepl 语句时的关系
- 我觉得很多代码可以简化,但我不知道如何简化
让我们考虑这个最小的例子:
names
是一个字符向量,存储 3 个不同的人的名字,以各种方式书写
names
应该简化(重新编码),以便多次出现的人名以相同的方式存储
让我们假设 Johnatan 是第一约翰,
约翰尼和约翰尼都是约翰二世,
John, John D., John Doe 是第三约翰。
凭借我有限的 R
知识,我得出了这个解决方案:
names <- c("John", "Johnatan", "Johnnie", "John D.", "John Doe", "johnnie")
names[grepl("johna", names, ignore.case = TRUE)] <- "First John"
names[grepl("johnn", names, ignore.case = TRUE)] <- "Second John"
names[grepl("john d*", names, ignore.case = TRUE)] <- "Third John"
此时 john
我不知道如何将 Third John
重新编码为
names[grepl("john", names, ignore.case = TRUE)]
会接走 names
的所有约翰。
问题:
我该如何处理这种关系,希望在某种程度上比我目前所写的更优雅?
感谢您的任何提示和建议。
temp = c(Johnatan = "First John", johnnie = "Second John", John = "Third John")
temp[apply(X = sapply(names(temp),
function(x) grepl(pattern = x,
x = names,
ignore.case = TRUE)),
MARGIN = 1,
FUN = function(x) head(which(x), 1))]
# John Johnatan johnnie John John johnnie
# "Third John" "First John" "Second John" "Third John" "Third John" "Second John"
您可以为 "john"
:
使用单词边界 (\b
)
names <- c("John", "Johnatan", "Johnnie", "John D.", "John Doe", "johnnie")
names2 = names
names2[grepl("johna", names, ignore.case = TRUE)] <- "First John"
names2[grepl("johnn", names, ignore.case = TRUE)] <- "Second John"
names2[grepl("john(\b|\sd.*)", names, ignore.case = TRUE)] <- "Third John"
或 case_when
来自 dplyr
:
library(dplyr)
names = case_when(grepl("johna", names, ignore.case = TRUE) ~ "First Join",
grepl("johnn", names, ignore.case = TRUE) ~ "Second Join",
grepl("john(\b|\sd.*)", names, ignore.case = TRUE) ~ "Third Join")
注:
\b
匹配单词边界,可以是 space 或标点符号。例如 johnatan
不会匹配,因为 john
跟在另一个字母 a
之后,而不是单词边界。
\s
匹配 space.
d.*
匹配 d
后跟任何内容 (.
) 零次。
( | )
是匹配 |
.
左侧或右侧的捕获组
john(\b|\sd.*)
匹配 john
后跟单词边界或 space 后跟 d
和任何零次或多次。因此匹配 "john"
、"john d."
和 "john doe"
(ignore.case = TRUE
会处理这些情况)。
结果:
> names2
[1] "Third John" "First John" "Second John" "Third John" "Third John" "Second John"
我正在做一项作业,需要清除大量混乱的字符串数据。
我已经解决了大多数问题,但遇到了两个问题:
- 使用多个 grepl 语句时的关系
- 我觉得很多代码可以简化,但我不知道如何简化
让我们考虑这个最小的例子:
names
是一个字符向量,存储 3 个不同的人的名字,以各种方式书写
names
应该简化(重新编码),以便多次出现的人名以相同的方式存储
让我们假设 Johnatan 是第一约翰,
约翰尼和约翰尼都是约翰二世,
John, John D., John Doe 是第三约翰。
凭借我有限的 R
知识,我得出了这个解决方案:
names <- c("John", "Johnatan", "Johnnie", "John D.", "John Doe", "johnnie")
names[grepl("johna", names, ignore.case = TRUE)] <- "First John"
names[grepl("johnn", names, ignore.case = TRUE)] <- "Second John"
names[grepl("john d*", names, ignore.case = TRUE)] <- "Third John"
此时 john
我不知道如何将 Third John
重新编码为
names[grepl("john", names, ignore.case = TRUE)]
会接走 names
的所有约翰。
问题:
我该如何处理这种关系,希望在某种程度上比我目前所写的更优雅?
感谢您的任何提示和建议。
temp = c(Johnatan = "First John", johnnie = "Second John", John = "Third John")
temp[apply(X = sapply(names(temp),
function(x) grepl(pattern = x,
x = names,
ignore.case = TRUE)),
MARGIN = 1,
FUN = function(x) head(which(x), 1))]
# John Johnatan johnnie John John johnnie
# "Third John" "First John" "Second John" "Third John" "Third John" "Second John"
您可以为 "john"
:
\b
)
names <- c("John", "Johnatan", "Johnnie", "John D.", "John Doe", "johnnie")
names2 = names
names2[grepl("johna", names, ignore.case = TRUE)] <- "First John"
names2[grepl("johnn", names, ignore.case = TRUE)] <- "Second John"
names2[grepl("john(\b|\sd.*)", names, ignore.case = TRUE)] <- "Third John"
或 case_when
来自 dplyr
:
library(dplyr)
names = case_when(grepl("johna", names, ignore.case = TRUE) ~ "First Join",
grepl("johnn", names, ignore.case = TRUE) ~ "Second Join",
grepl("john(\b|\sd.*)", names, ignore.case = TRUE) ~ "Third Join")
注:
\b
匹配单词边界,可以是 space 或标点符号。例如johnatan
不会匹配,因为john
跟在另一个字母a
之后,而不是单词边界。\s
匹配 space.d.*
匹配d
后跟任何内容 (.
) 零次。( | )
是匹配|
. 左侧或右侧的捕获组
john(\b|\sd.*)
匹配john
后跟单词边界或 space 后跟d
和任何零次或多次。因此匹配"john"
、"john d."
和"john doe"
(ignore.case = TRUE
会处理这些情况)。
结果:
> names2
[1] "Third John" "First John" "Second John" "Third John" "Third John" "Second John"