【问题标题】:Filter a data frame based on matching values (exact) between two columns根据两列之间的匹配值(精确)过滤数据框
【发布时间】:2016-10-01 00:41:18
【问题描述】:

我有一个包含两列的数据框。一列包含句子列表,另一列包含单词。例如:

words   sentences
loose   Loose connection several times a day on my tablet.  
loud    People don't speak loud or clear enough to hear voicemails
vice    I strongly advice you to fix this issue
advice  I strongly advice you to fix this issue

现在我想过滤这个数据框,只得到那些单词与句子中的单词完全匹配的行:

words   sentences
loose   Loose connection several times a day on my tablet.  
loud    People don't speak loud or clear enough to hear voicemails
advice  I strongly advice you to fix this issue   

单词“vice”不完全匹配,因此必须将其删除。我在数据框中有近 20k 行。有人可以建议我使用哪种方法来完成这项任务,这样我就不会损失太多性能。

【问题讨论】:

    标签: r dataframe match


    【解决方案1】:

    使用:

    library(stringi)
    df[stri_detect_regex(tolower(df$sentences), paste0('\\b',df$words,'\\b')),]
    

    你得到:

       words                                                  sentences
    1  loose         Loose connection several times a day on my tablet.
    2   loud People don't speak loud or clear enough to hear voicemails
    4 advice                    I strongly advice you to fix this issue
    

    解释:

    • tolower将句子中的大写字母转换为小写字母。
    • 通过将words 中的单词包装在wordboundaries (\\b) 中,使用paste0 创建一个正则表达式向量。
    • 使用 stringi-package 中的 stri_detect_regex 查看在哪些行中没有匹配项,从而生成具有 TRUEFALSE 值的逻辑向量。
    • 带有逻辑向量的子集。

    您也可以使用stringr 包中的str_detect(实际上是stringi 包的包装):

    library(stringr)
    df[str_detect(tolower(df$sentences), paste0('\\b',df$words,'\\b')),]
    

    使用过的数据:

    df <- structure(list(words = c("loose", "loud", "vice", "advice"), 
                         sentences = c("Loose connection several times a day on my tablet.", 
                                       "People don't speak loud or clear enough to hear voicemails", 
                                       "I strongly advice you to fix this issue", "I strongly advice you to fix this issue")), 
                    .Names = c("words", "sentences"), class = "data.frame", row.names = c(NA, -4L))
    

    【讨论】:

      【解决方案2】:

      您可以尝试以下方法:

      df[apply(df, 1, function(x) tolower(x[1]) %in% tolower(unlist(strsplit(x[2], split='\\s+')))),]
      
      df
         words                                                sentences
      1  loose       Loose connection several times a day on my tablet.
      2   loud People dont speak loud or clear enough to hear voicemail
      4 advice          advice  I strongly advice you to fix this issue
      

      【讨论】:

      • 这种方法比使用 str_detect 更快,因此接受这个作为答案。
      【解决方案3】:

      最简单的解决方案是使用 stringr 包:

      df<- data.frame(words=c("went","zero", "vice"), sent=c("a man went to the park","one minus one is 0","any advice?"))
      
      df$words <- paste0(" ",df$words," ")
      df$sent <- paste0(" ",df$sent," ")
      
      
      df$match <- str_detect(df$sent,df$words)
      
      df.res <- df[df$match > 0,]
      df.res$match<-NULL
      df.res
      

      【讨论】:

      • 这并没有给出 OP 数据的首选输出。
      • 现在工作,但它肯定不再是最简单的解决方案了。此外,sent 列的内容发生了变化,这不是 OP 的意图。
      • 基本上你的版本比我的更优雅 - 但我最近才开始自己开发我的 R 技能!
      • 我无意敌对,但请考虑以下几点:从所需的输出来看,不区分大小写的匹配是 OP 所追求的。关于是否添加到另一个答案:起初您在答案中使用了 stri_extract 并且您的答案版本没有提供所需的输出。在我发布答案后,您切换到 str_detect 方式。 (顺便说一句:我没有投反对票)
      • 我正在回复其他人,他们已经删除了他们的 cmets,你根本没有敌意
      猜你喜欢
      • 2017-12-23
      • 2018-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-17
      • 2022-01-17
      • 1970-01-01
      相关资源
      最近更新 更多