【问题标题】:string match: words + characters字符串匹配:单词+字符
【发布时间】:2019-01-14 16:16:19
【问题描述】:

我正在尝试搜索一个数据框以匹配一个字符串,我从一个充满注释的列中创建了一个对象。

举个例子:

我正在寻找任何可能匹配注释的行

mph_words<-c(">10", "> 10", ">20", "> 20")

而一行代码可能类似于:

> lc_notes[1703]
[1] "collected 1.667 man-hr total. mostly cloudy, windy with gusts >20 mph."

如您所见,一些注释在“”和数字之间有空格,因此使用 strsplit 进行搜索并不理想,因为我确实需要保留“数字。

我试过了

> mph_words %in% lc_notes[2000]
[1] FALSE FALSE FALSE FALSE

> pmatch(mph_words, lc_notes[1703])
[1] NA NA NA NA

grepl(lc_notes[1703],mph_words)
[1] FALSE FALSE FALSE FALSE

> str_detect(mph_words,lc_notes[1703])
[1] FALSE FALSE FALSE FALSE

> for (word in 1:length(mph_words)){
+   print(str_extract(mph_words[word],lc_notes[1703]))
+ }
[1] NA
[1] NA
[1] NA
[1] NA

我不确定接下来要尝试什么。如果它是一个正则表达式,你可以在你的答案中解释它吗?我试图更好地理解正则表达式。

编辑 我正在尝试打印出在 mph_words 中具有特定字符之一的行。因此,代码将搜索我的 lc_notes 中的每一行并打印第 1703 行。

提前谢谢你!

【问题讨论】:

  • 感谢大家的快速帮助,更重要的是代码解释! @G5W -- 感谢所有编辑,但保留 # 很重要,因为 mph 的值对于代码的下一部分很重要。
  • @nate 谢谢!我应该更好地澄清(仍在学习如何提问)但是 lc_notes 在 ">"/"

标签: r string string-matching


【解决方案1】:

已编辑以匹配已编辑的问题:
要查找行号,请使用grep

grep("[<>]\\s*\\d+\\b",  lc_notes)

[&lt;&gt;] 匹配
\\s* 允许可选空格
\\d 匹配以下数字。

grep 将给出匹配的行数。

【讨论】:

  • 我刚刚尝试复制 + 粘贴您的代码,但得到了这个:> sub(".*([]\s*\d+\b).*", "\\1", lc_notes ) 错误:'\s' 是从 "".*([]\s" 开始的字符串中无法识别的转义,您能解释一下您的代码吗?谢谢!
  • 这是我得到的错误:错误:'\s' is an unrecognized escape in string starting "".*([]\s"
  • 现在修复它。试试新版本。
  • 谢谢!我得到了打印输出,但我正在澄清我的问题。感谢您的正则表达式解释——这非常有帮助
【解决方案2】:

为此,我会使用 applystringr::str_detect

lc_notes <- c("collected 1.667 man-hr total. mostly cloudy, windy with gusts >20 mph.",
              "collected 1.667 man-hr total. mostly cloudy, windy with gusts > 20 mph.",
              "collected 1.667 man-hr total. mostly cloudy, windy with gusts of 20 mph.")
mph_words<-c(">10", "> 10", ">20", "> 20")

sapply(lc_notes, function(x) any(str_detect(x, mph_words)))

collected 1.667 man-hr total. mostly cloudy, windy with gusts >20 mph. 
                                                                    TRUE 
collected 1.667 man-hr total. mostly cloudy, windy with gusts > 20 mph. 
                                                                    TRUE 
collected 1.667 man-hr total. mostly cloudy, windy with gusts of 20 mph. 
                                                                   FALSE 

sapply 将遍历lc_notes 向量的每个元素,对每个元素应用测试。然后通过使用any,我们将向量简化为单个逻辑值。

如果您想要行号而不是逻辑向量,请使用which 函数:

unname(which(sapply(lc_notes, function(x) any(str_detect(x, mph_words)))))
[1] 1 2

我在这里使用了unname 来强调这个返回的向量是lc_notes 中匹配任何正则表达式模式的项目的索引。你也可以反其道而行之,在其上调用names 以获取该行的文本:

names(which(sapply(lc_notes, function(x) any(str_detect(x, mph_words)))))
[1] "collected 1.667 man-hr total. mostly cloudy, windy with gusts >20 mph." 
[2] "collected 1.667 man-hr total. mostly cloudy, windy with gusts > 20 mph."

如果您想要一个更简单的正则表达式,可以匹配有或没有空格,请在空格字符上使用? 可选量词:

mph_words<-c("> ?10", "> ?20")

【讨论】:

  • 谢谢!这正是我所希望的!我真的很感激?选项,特别是名称/取消名称选项!
【解决方案3】:

这是一种使用strsplitlapply的方法

# standardize (get rid of white spaces between <,> and digits in mph_words
mph_words <- unique(gsub('([<>])\\s{0,}(\\d+)', '\\1\\2', mph_words, perl = TRUE))        
# match 
check <- lapply(1:length(lc_notes), 
                function (k) any(mph_words %in% unlist(strsplit(lc_notes[k], ' '))))
check
# [[1]]
# [1] TRUE

# [[2]]
# [1] TRUE

# [[3]]
# [1] FALSE

# Finally printing the indices with a match
which(unlist(check))
# [1] 1 2

有数据

mph_words <- c(">10", "> 10", ">20", "> 20")  
lc_notes <- "collected 1.667 man-hr total. mostly cloudy, windy with gusts >20 mph."
lc_notes <- c(lc_notes, 'test >10', '>15')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-15
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多