【问题标题】:Pattern matching using a wildcard使用通配符进行模式匹配
【发布时间】:2011-04-28 18:47:46
【问题描述】:

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

我找到了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*") )

但是,这些都不起作用。我不确定是否应该使用其他功能来尝试执行此操作。

【问题讨论】:

    标签: r pattern-matching wildcard


    【解决方案1】:

    如果你想检查数据框中的元素,你不应该使用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
    

    编辑:在子集()中添加一个“正确”使用 glob2rx:

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

    在我回到这个问题之前,我认为我实际上并不理解glob2rx。 (我确实理解了作为提问者困难根源的范围界定问题。任何阅读本文的人现在都应该向下滚动到 Gavin 的答案并投票。)

    【讨论】:

    • 如果你想排除向量,你可以把“-”运算符放在“grep”之前
    • @BondedDust 如果我只想要以“blue”开头的元素,而不想要其中包含“blue”的元素怎么办?例如,我想从此 data.frame a &lt;- data.frame( x = c('red','blue1','blue2', 'red2','lightblue','darkblue')) 中仅选择“blue1”和“blue2”,非常感谢您的帮助。
    • 以“蓝色”开头的模式为"^blue"。见?regex
    【解决方案2】:

    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() 的作用以及如何使用它?

    【讨论】:

    • 确实如此。即使在这么晚的日子里,我也很高兴能学到新东西。我想我从来没有理解过 glob2rx 是什么高级函数。
    【解决方案3】:

    您在正确的轨道上 - 您应该在谷歌上搜索的关键字是正则表达式。 R 确实以比使用grep() 和其他一些替代方案更直接的方式支持它们。

    这里有详细讨论:http://www.regular-expressions.info/rlanguage.html

    【讨论】:

      【解决方案4】:

      如果您确实想使用通配符来标识特定变量,则可以使用ls()grep() 的组合,如下所示:

      l = ls()
      vars.with.result &lt;- l[grep("result", l)]

      【讨论】:

        【解决方案5】:

        你也可以使用包data.table和它的Like函数,详情如下 How to select R data.table rows based on substring match (a la SQL like)

        【讨论】:

          【解决方案6】:

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

          filter(str_detect(a, "blue"))
          

          它会考虑 blue 的所有实例,例如 blue1blue2

          这个命令和

          基本一样
          filter(str_detect(a, "blue") == TRUE)
          

          如果蓝调是大写和小写,你可以这样做:

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

          我希望它对正在寻找类似解决方案的人有所帮助。

          【讨论】:

            猜你喜欢
            • 2023-01-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-09-08
            • 1970-01-01
            • 2013-02-27
            相关资源
            最近更新 更多