查找一个字符串是否出现在另一个字符串之前
Find if a string appear before another string
我有一个包含患者地址的字符串变量。我的目标是标记住在“401 30th street”的患者。我想标记在“30”之前包含数字“401”的字符串,以避免标记像数字 3 这样的地址。我下面的代码只标记字符串是否包含数字 401 和 30,而不考虑它们的位置。任何帮助将不胜感激。
ADDRESS Outcome
1 401 300th st FALSE
2 40120 30 street FALSE
3 30 401 plz TRUE
4 401 30th st TRUE
5 401 e gibbsborro rd, 305 FALSE
6 401 e 30th street, shelter TRUE
7 401 east 30st TRUE
8 401 e30th street, 3 TRUE
9 77-02 30th ave, 3rd fl FALSE
10 401 e30 st. TRUE
structure(list(ADDRESS = c("401 300th st", "40120 30 street",
"30 401 plz", "401 30th st", "401 e gibbsborro rd, 305", "401 e 30th street, shelter",
"401 east 30st", "401 e30th street, 3", "77-02 30th ave, 3rd fl",
"401 e30 st."), Outcome = c(FALSE, FALSE, TRUE, TRUE, FALSE,
TRUE, TRUE, TRUE, FALSE, TRUE)), class = "data.frame", row.names = c(NA,
-10L))
loction <- location %>%
mutate(ADDRESS = tolower(ADDRESS),
st30 = grepl("\<401\>", ADDRESS) &
grepl("\<30\>|\<30th\>|\<30st\>|\<e30th\>|\<e30\>", ADDRESS))
编辑:我向示例数据以及我希望生成的变量添加了新的观察结果。这个想法是标记来自 401 30th Street 的患者。为此,我想在 30|30th|s30|east30|e30st 等之前标记数字为 401 的字符串。我希望这能澄清我在寻找什么。谢谢
试试
library(dplyr)
library(stringr)
location %>%
mutate(flag = str_detect(ADDRESS, '401\b.*\b30'))
你可以试试这个:
library(dplyr)
library(stringr)
location %>%
mutate(flag = str_detect(ADDRESS, '^[^30]*401 .*30.*$'))
输出:
ADDRESS flag
1 401 30th st TRUE
2 40120 30 street FALSE
3 30 401 st FALSE
4 401 30th st TRUE
要解决更新后的问题,您需要使用
grepl("^(?=.*\b401\b)(?=.*?\be?30(?:th|st)?\b)", ADDRESS, perl=TRUE)
见regex demo and the R demo。 详情:
^
- 字符串开头
(?=.*\b401\b)
- 在除换行字符以外的任何零个或多个字符之后的某处必须有 401
个完整单词,尽可能多
(?=.*?\be?30(?:th|st)?\b)
- 必须有一个单词边界、一个可选的 e
、30
,然后是一个可选的 th
或 st
字符序列和一个除换行字符外的任何零个或多个字符之后的某处的单词边界,尽可能多
当您使用两个单独的 `grepl` 调用时,将搜索匹配项,而不考虑它们在字符串中出现的顺序。
按顺序加工两个子串表示
- 匹配最左边的模式
- 匹配任何字符(因为正则表达式引擎必须以某种方式到达第二个模式)与
.*
、.*?
、[=24 这样的模式=]、(?s:.)*?
(后两者符合PCRE/ICU)等
- 匹配最右边的模式。
所以,在这里,由于输入中没有换行符,您可能可以使用
df %>%
mutate(st30 = grepl('401.*?30', ADDRESS))
但是、401
和 30
上面的模式在任何上下文中都是匹配的。如果要将它们匹配为精确的整数值,则需要使用 numeric 边界:
grepl('(?<!\d)401(?!\d).*?(?<!\d)30(?!\d)', ADDRESS, perl=TRUE)
或许,您也可以在这些数字模式的开头使用简单的单词边界(即在它们之前,不允许使用字母、数字或下划线):
grepl('\b401(?!\d).*?\b30(?!\d)', ADDRESS, perl=TRUE)
我有一个包含患者地址的字符串变量。我的目标是标记住在“401 30th street”的患者。我想标记在“30”之前包含数字“401”的字符串,以避免标记像数字 3 这样的地址。我下面的代码只标记字符串是否包含数字 401 和 30,而不考虑它们的位置。任何帮助将不胜感激。
ADDRESS Outcome
1 401 300th st FALSE
2 40120 30 street FALSE
3 30 401 plz TRUE
4 401 30th st TRUE
5 401 e gibbsborro rd, 305 FALSE
6 401 e 30th street, shelter TRUE
7 401 east 30st TRUE
8 401 e30th street, 3 TRUE
9 77-02 30th ave, 3rd fl FALSE
10 401 e30 st. TRUE
structure(list(ADDRESS = c("401 300th st", "40120 30 street",
"30 401 plz", "401 30th st", "401 e gibbsborro rd, 305", "401 e 30th street, shelter",
"401 east 30st", "401 e30th street, 3", "77-02 30th ave, 3rd fl",
"401 e30 st."), Outcome = c(FALSE, FALSE, TRUE, TRUE, FALSE,
TRUE, TRUE, TRUE, FALSE, TRUE)), class = "data.frame", row.names = c(NA,
-10L))
loction <- location %>%
mutate(ADDRESS = tolower(ADDRESS),
st30 = grepl("\<401\>", ADDRESS) &
grepl("\<30\>|\<30th\>|\<30st\>|\<e30th\>|\<e30\>", ADDRESS))
编辑:我向示例数据以及我希望生成的变量添加了新的观察结果。这个想法是标记来自 401 30th Street 的患者。为此,我想在 30|30th|s30|east30|e30st 等之前标记数字为 401 的字符串。我希望这能澄清我在寻找什么。谢谢
试试
library(dplyr)
library(stringr)
location %>%
mutate(flag = str_detect(ADDRESS, '401\b.*\b30'))
你可以试试这个:
library(dplyr)
library(stringr)
location %>%
mutate(flag = str_detect(ADDRESS, '^[^30]*401 .*30.*$'))
输出:
ADDRESS flag
1 401 30th st TRUE
2 40120 30 street FALSE
3 30 401 st FALSE
4 401 30th st TRUE
要解决更新后的问题,您需要使用
grepl("^(?=.*\b401\b)(?=.*?\be?30(?:th|st)?\b)", ADDRESS, perl=TRUE)
见regex demo and the R demo。 详情:
^
- 字符串开头(?=.*\b401\b)
- 在除换行字符以外的任何零个或多个字符之后的某处必须有401
个完整单词,尽可能多(?=.*?\be?30(?:th|st)?\b)
- 必须有一个单词边界、一个可选的e
、30
,然后是一个可选的th
或st
字符序列和一个除换行字符外的任何零个或多个字符之后的某处的单词边界,尽可能多
当您使用两个单独的 `grepl` 调用时,将搜索匹配项,而不考虑它们在字符串中出现的顺序。
按顺序加工两个子串表示
- 匹配最左边的模式
- 匹配任何字符(因为正则表达式引擎必须以某种方式到达第二个模式)与
.*
、.*?
、[=24 这样的模式=]、(?s:.)*?
(后两者符合PCRE/ICU)等 - 匹配最右边的模式。
所以,在这里,由于输入中没有换行符,您可能可以使用
df %>%
mutate(st30 = grepl('401.*?30', ADDRESS))
但是、401
和 30
上面的模式在任何上下文中都是匹配的。如果要将它们匹配为精确的整数值,则需要使用 numeric 边界:
grepl('(?<!\d)401(?!\d).*?(?<!\d)30(?!\d)', ADDRESS, perl=TRUE)
或许,您也可以在这些数字模式的开头使用简单的单词边界(即在它们之前,不允许使用字母、数字或下划线):
grepl('\b401(?!\d).*?\b30(?!\d)', ADDRESS, perl=TRUE)