【问题标题】:Extracting a number following specific text in R在R中的特定文本之后提取一个数字
【发布时间】:2021-05-05 16:40:18
【问题描述】:

我有一个数据框,其中包含一列完整的文本。我需要捕获某个短语之后的数字(可能是长度为 1 到 4 位的任意位数),即 'Floor Area''floor area' 。我的数据将如下所示:

"A beautiful flat on the 3rd floor with floor area: 50 sqm and a lift"
"Newbuild flat. Floor Area: 30 sq.m" 
"6 bed house with floor area 50 sqm, lot area 25 sqm"

如果我尝试仅提取数字,或者如果我从 sqm 回头看,我有时会错误地得到很多区域。如果有人可以帮助我使用前瞻正则表达式或 stringr 中的类似表达式,我将不胜感激。正则表达式对我来说是一个弱点。非常感谢。

【问题讨论】:

    标签: regex r stringr


    【解决方案1】:

    在单词之前或之后提取数字的常用技术是匹配所有字符串,直到单词或数字或数字和单词,同时捕获数字,然后匹配字符串的其余部分并使用 sub:

    替换为捕获的子字符串
    # Extract the first number after a word:
    as.integer(sub(".*?<WORD_OR_PATTERN_HERE>.*?(\\d+).*", "\\1", x))
    
    # Extract the first number after a word:
    as.integer(sub(".*?(\\d+)\\s*<WORD_OR_PATTERN_HERE>.*", "\\1", x))
    

    注意:将\\d+ 替换为\\d+(?:\\.\\d+)? 以匹配整数或浮点数(为了与上面的代码保持一致,请记住将as.integer 更改为as.numeric)。 \\s* 匹配第二个 sub 中的 0 个或多个空格。

    对于当前场景,可能的解决方案如下所示

    v <- c("A beautiful flat on the 3rd floor with floor area: 50 sqm and a lift","Newbuild flat. Floor Area: 30 sq.m","6 bed house with floor area 50 sqm, lot area 25 sqm")
    as.integer(sub("(?i).*?\\bfloor area:?\\s*(\\d+).*", "\\1", v))
    # [1] 50 30 50
    

    请参阅regex demo

    您还可以利用 stringr 中的 str_match 捕获机制并获取第二列值 ([,2]):

    > library(stringr)
    > v <- c("A beautiful flat on the 3rd floor with floor area: 50 sqm and a lift","Newbuild flat. Floor Area: 30 sq.m","6 bed house with floor area 50 sqm, lot area 25 sqm")
    > as.integer(str_match(v, "(?i)\\bfloor area:?\\s*(\\d+)")[,2])
    [1] 50 30 50
    

    请参阅regex demo

    正则表达式匹配:

    • (?i) - 不区分大小写
    • \\bfloor area:? - 整个单词(\b 是单词边界)floor area 后跟可选的:(出现一次或零次,?
    • \\s* - 零个或多个空格
    • (\\d+) - 第 1 组(将在 [,2] 中)捕获一位或多位数字

    R demo online

    【讨论】:

    • 这很棒。非常感谢,感谢您提供的详细解释!
    • 要捕获小数,可以将(\\d+)替换为(\\d+(?:.\\d+)),记住也要将as.integer改为as.numeric
    【解决方案2】:

    以下正则表达式可以帮助您入门:

    [Ff]loor\s+[Aa]rea:?\s+(\d{1,4})
    

    The DEMO.

    【讨论】:

      【解决方案3】:

      将以下正则表达式与不区分大小写的匹配一起使用:

      floor\s*area:?\s*(\d{1,4})
      

      【讨论】:

        【解决方案4】:

        您需要查看正则表达式。

        str_extract_all(x, "\\b[Ff]loor [Aa]rea:?\\s*\\K\\d+", perl=T)
        

        str_extract_all(x, "(?i)\\bfloor area:?\\s*\\K\\d+", perl=T)
        

        DEMO

        不知道为什么上面的代码不会返回任何东西。你也可以试试sub

        > sub(".*\\b[Ff]loor\\s+[Aa]rea:?\\s*(\\d+).*", "\\1", x)
        [1] "50" "30" "50"
        

        【讨论】:

        • perl 不是str_extract_all() 的参数
        • 那么,st_extract_all 中不需要 perl arg 吗?
        • for 'perl=TRUE' 表示“未使用的参数”,不使用 perl 它只显示“character(0)”
        • @AvinashRaj:stringr 的最新版本使用 ICU 正则表达式库。 :) 它不支持\K
        • 这是谁干的?打算用烂鱼给stringr包的开发者一巴掌。
        【解决方案5】:
        text<- "A beautiful flat on the 3rd floor with floor area: 50 sqm and a lift"
        
        unique(na.omit(as.numeric(unlist(strsplit(unlist(text), "[^0-9]+")))))
        # [1]  3 50
        

        希望这会有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-02-02
          • 2020-05-16
          • 1970-01-01
          • 2022-01-18
          • 1970-01-01
          • 2015-06-23
          • 1970-01-01
          相关资源
          最近更新 更多