通配符匹配模式

42

如何使用通配符识别字符串?

我找到了 glob2rx,但我不太明白如何使用它。我尝试使用以下代码选择以单词 blue 开头的数据框的行:

# make data frame
a <- data.frame( x =  c('red','blue1','blue2', 'red2'))

# 1
result <- subset(a, x == glob2rx("blue*") )

# 2
test = ls(pattern = glob2rx("blue*"))
result2 <- subset(a, x == test )

# 3
result3 <- subset(a, x == pattern("blue*") )

但是这两个都没有起作用。我不确定是否应该使用其他函数来尝试实现此操作。

6个回答

44

如果您想检查数据框中的元素,不应使用ls()函数。该函数只查看当前工作空间中对象的名称(或者如果在当前环境中的函数内使用)。行名称或该对象内部的元素对ls()不可见(当然,除非您向ls(.)调用添加环境参数)。尝试使用grep()函数,它是用于模式匹配字符向量的主力函数:

result <- a[ grep("blue", a$x) , ]  # Note need to use `a$` to get at the `x`

如果您想使用子集,则考虑与其密切相关的函数grepl(),该函数返回逻辑向量,可用于子集参数:
subset(a, grepl("blue", a$x))
      x
2 blue1
3 blue2

编辑:在subset()中添加一个“合适”的glob2rx使用:

result <- subset(a,  grepl(glob2rx("blue*") , x) )
result
      x
2 blue1
3 blue2

我认为直到我回到这个问题,我才真正理解了glob2rx。(我确实理解了提问者遇到的作用域问题。任何阅读此内容的人现在应该向下滚动到Gavin的答案并点赞。)


1
如果你想排除向量,那么可以在“grep”之前加上“-”运算符。 - Thieme Hennis
@BondedDust 如果我只想选择以“blue”开头的元素,而不是包含“blue”的元素呢?例如,我想从这个数据框中仅选择“blue1”和“blue2”。a <- data.frame( x = c('red','blue1','blue2', 'red2','lightblue','darkblue')) 如果您能帮忙,我将非常感激。 - Darwin PC
1
以“blue”开头的模式应为“^blue”。请参阅?regex - IRTFM

36

glob2rx()函数将包含通配符的模式转换为等效的正则表达式。然后,您需要将这个正则表达式传递给R语言的某个模式匹配工具。

如果您想匹配通配符为*的字符串"blue*",并且使用的不是正则表达式而是通配符,那么可以使用glob2rx()函数将通配符模式转换为可用的正则表达式:

> glob2rx("blue*")
[1] "^blue"

返回的对象 正则表达式。

考虑你的数据:

x <- c('red','blue1','blue2', 'red2')
我们可以使用grep()或类似的工具进行模式匹配:
> grx <- glob2rx("blue*")
> grep(grx, x)
[1] 2 3
> grep(grx, x, value = TRUE)
[1] "blue1" "blue2"
> grepl(grx, x)
[1] FALSE  TRUE  TRUE FALSE

关于您发布的选择行问题

> a <- data.frame(x =  c('red','blue1','blue2', 'red2'))
> with(a, a[grepl(grx, x), ])
[1] blue1 blue2
Levels: blue1 blue2 red red2
> with(a, a[grep(grx, x), ])
[1] blue1 blue2
Levels: blue1 blue2 red red2

或者通过subset()方法:

> with(a, subset(a, subset = grepl(grx, x)))
      x
2 blue1
3 blue2
希望这解释清楚了 grob2rx() 是做什么的以及如何使用它?

1
是的,我很高兴在这个时候学到了新东西。我认为我从来没有真正理解过高级函数 glob2rx 是什么。 - IRTFM

4

2

2
如果你想使用通配符来识别特定的变量,那么可以结合 ls()grep() 使用,如下所示:

l = ls()
vars.with.result <- l[grep("result", l)]


0

另一种实现您所需功能的方法是通过dplyr()

filter(str_detect(a, "blue"))

它将考虑所有蓝色的实例,例如blue1blue2

这个命令基本上与...相同

filter(str_detect(a, "blue") == TRUE)

如果蓝色的大小写不一致,你可以这样做:

filter(str_detect(str_to_lower(a), "blue"))

我希望这能帮助到正在寻找类似解决方案的人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接