使用 R gsub 仅从字符串中返回两位数字符?

Using R gsub to only return double digit characters from string?

提问人:vizidea 提问时间:10/21/2023 更新时间:10/23/2023 访问量:79

问:

我有一个变量,其值如下:

example <- c("positive_1", "positive_2", "test_20_curve", "test_60_point", "percent_total")

有没有办法只从向量中返回“20”和“60”?

我目前有

gsub(".*([0-9]{2}).*", "\\1", example)

哪个输出

[1] "positive_1"    "positive_2"    "20"            "60"            "percent_total"

我想知道是否有一种方法可以使任何没有两位数的值显示为 NA。

提前致谢!

r 正则表达式

评论

0赞 Cary Swoveland 10/21/2023
“pos_20”呢?“pos_200_pos”?"_20"?"20"?"20_"?“pos_2_pos20_pos_200”?数字总是以“_”开头吗?数字是总是在字符串的末尾还是后跟“_”?您是否希望使用正则表达式来确认字符串仅包含数字、下划线和小写字母,如示例中所示?请回答这些问题,并通过编辑您的问题(而不是在评论中详细说明)来澄清。很少能单独使用示例来明确地提出问题。你需要一个清晰的文字陈述。示例仅供说明之用。

答:

2赞 Wiktor Stribiżew 10/21/2023 #1

stringr::str_extract方法

你可以使用

example <- c("positive_1", "positive_2", "test_20_curve", "test_60_point", "percent_total")
library(stringr)
str_extract(example, "(?<!\\d)\\d{2}(?!\\d)")
## => [1] NA   NA   "20" "60" NA  

请参阅 R 演示注意:提取模式的第一个匹配项。如果需要最后一个,请使用 and,然后 .str_extractlibrary(stringi)stri_extract_last_regex(example, "(?<!\\d)\\d{2}(?!\\d)")

细节

  • (?<!\d)- 在左边,不能有数字
  • \d{2}- 两位数
  • (?!\d)- 不紧跟另一个数字。

sub方法

example <- c("positive_1", "positive_2", "test_20_curve", "test_60_point", "percent_total")
res <- sub("^(?:(?:.*\\D)?(\\d{2})(?:\\D.*)?|.+)$", "\\1", example)
res <- res[nzchar(res)]
res
## => [1] "20" "60"

请参阅 R 演示

图案细节

  • ^- 字符串的开头
  • (?:- 以下两种选择之一:
    • |.+)
    • (?:.*\D)?- 任何非数字字符的可选序列,然后是字符串的其余部分
    • (\d{2})- 第 1 组(替换模式中指值):两位数\1
    • (?:\D.*)?- 任何非数字字符的可选序列,然后是字符串的其余部分
  • |-或
    • .+- 一个或多个字符,尽可能多的字符
  • )- 外部分组的末尾(以便任一模式部分可以匹配整个字符串)
  • $- 字符串末尾。

注意这里就足够了,因为我们在整个字符串匹配时执行一次替换。sub

如果字符串中没有只有 2 位数字,则 的结果将是一个空字符串,因此我们需要使用 来摆脱它们。subres <- res[nzchar(res)]

注意:如果出现多个 2 位数字,则使用此方法返回最后一个数字。要获取第一个,请使用 .sub("^(?:(?:.*?\\D)?(\\d{2})(?:\\D.*)?|.+)$", "\\1", example, perl=TRUE)

1赞 TarJae 10/21/2023 #2

我们首先提取两位数 然后,我们检查向量的每个元素中是否有一个两位数,并且 将其他替换为 NAgsubgrepl

example <- c("positive_1", "positive_2", "test_20_curve", "test_60_point", "percent_total")

x <- gsub(".*?([0-9]{2}).*", "\\1", example)
x[!grepl("[0-9]{2}", example)] <- NA

x
[1] NA   NA   "20" "60" NA  

评论

1赞 GuedesBF 10/21/2023
提取数字两次对我来说看起来有点太奇怪了。至少应该有点低效。为什么不在步骤#2中使用更简单的解决方案呢?nchar
1赞 DuesserBaest 10/23/2023 #3

怎么样:

example <- c(
  "positive_1", 
  "positive_2", 
  "test_20_curve", 
  "test_60_point",
  "percent_total"
  )

res <- sub("^\\D+(\\d{2})?\\D.*$", "\\1", example)

res[grepl("^$", res)] <- NA

res

输出:

[1] NA   NA   "20" "60" NA  

\\D+测试非数字,然后

(\\d{2})捕获的两个数字,后跟

\\D*任意数量的非数字,确保匹配的位数不超过两位。

一切都匹配,只有捕获的两位数字被替换。

NA为任何空字符串插入。