【问题标题】:Get context around extracted word获取提取词的上下文
【发布时间】:2021-06-07 19:20:43
【问题描述】:

我从句子数据框中提取了关键字。我需要在关键字前后使用几个词来理解上下文并能够进行一些基本计数。

我已经尝试了多个 stringr 和 stringi 函数以及其他人在 SO 上针对类似问题提出的 grepl 函数。但是,找不到任何适合我的情况。

以下是我想要的。假设它是列出前两个字段的数据框或小标题。我需要/想要创建最右边的列 (keyword_w_context)。

在示例中,我提取了关键字后面的三个单词。但是,我想修改任何解决方案,以便获得 1、2、n。如果我能以同样的方式发帖也很好。

基本上,想要做一些类似于 mutate 的事情,它使用关键字周围的上下文词(之前/之后,见下文)创建一个新变量。

Sentence Keyword Keyword_w_context
The yellow lab dog is so cute. dog The yellow lab dog
The fluffy black cat purrs loudly. cat The fluffy black cat

非常感谢!

【问题讨论】:

    标签: r string stringr stringi


    【解决方案1】:

    您可能希望采用自然语言处理 (NLP) 方法,而不是基于正则表达式的方法。有很多框架可以做到这一点。一个很简单的方法是tidytext。下面是一个关于如何抓取围绕关键字的一堆单词的示例。

    你可能想玩弄这个来得到你想要的。听起来你想从中得到几样东西,所以我只选择了一个。

    library(tidytext)
    library(dplyr)
    library(tibble)
    
    df <- tibble(Sentence = c("The yellow lab dog is so cute.",
                              "The fluffy black cat purrs loudly."))
    keywords <- tibble(word = c("dog", "cat"), keyword = TRUE)
    
    df %>% 
      rowid_to_column() %>% 
      unnest_tokens("trigram", Sentence, token = "ngrams", n = 3, n_min = 2) %>%
      unnest_tokens("word", trigram, drop = FALSE) %>% 
      left_join(keywords, by = "word") %>% 
      filter(keyword)
    
    # A tibble: 10 x 4
       rowid trigram          word  keyword
       <int> <chr>            <chr> <lgl>  
     1     1 yellow lab dog   dog   TRUE   
     2     1 lab dog          dog   TRUE   
     3     1 lab dog is       dog   TRUE   
     4     1 dog is           dog   TRUE   
     5     1 dog is so        dog   TRUE   
     6     2 fluffy black cat cat   TRUE   
     7     2 black cat        cat   TRUE   
     8     2 black cat purrs  cat   TRUE   
     9     2 cat purrs        cat   TRUE   
    10     2 cat purrs loudly cat   TRUE
    

    如何在此基础上进行构建的示例如下所示。在这里,您可以跟踪从 n-gram 中找到每个单词的句子和位置。因此,您可以过滤关键字是第一个 word_pos 或其他的位置。

    df %>% 
      rowid_to_column("sentence_id") %>% 
      unnest_tokens("trigram", Sentence, token = "ngrams", n = 3, n_min = 3) %>%
      rowid_to_column("trigram_id") %>% 
      unnest_tokens("word", trigram, drop = FALSE) %>% 
      group_by(trigram_id) %>% 
      mutate(word_pos = row_number()) %>% 
      left_join(keywords, by = "word") %>%
      relocate(sentence_id, trigram_id, word_pos, trigram, word) %>% 
      filter(keyword, word_pos == 1)
    
    # A tibble: 2 x 6
    # Groups:   trigram_id [2]
      sentence_id trigram_id word_pos trigram          word  keyword
            <int>      <int>    <int> <chr>            <chr> <lgl>  
    1           1          4        1 dog is so        dog   TRUE   
    2           2          9        1 cat purrs loudly cat   TRUE 
    

    【讨论】:

    • 谢谢你,亚当。我没有想到一个 tidytext 方法。这非常有效!
    【解决方案2】:
    dat = read.table(text = 'Sentence   | Keyword | Keyword_w_context
    The yellow lab dog is so cute.|dog|The yellow lab dog
    The fluffy black cat purrs loudly.|cat|The fluffy black cat',sep="|",header=TRUE)
    
        
    n_before = 3
    n_after = 2
    
    
    # Note: This will give an error if you don't have enough words before or after
    dat %>% 
      mutate(Keyword_w_context_before = str_extract(string=Sentence,
                                                  pattern=paste0("(([A-Za-z]+)\\s){",n_before,"}",Keyword)),
             
             Keyword_w_context_after = str_extract(string=Sentence,
                                                   pattern=paste0(Keyword,"(\\s([A-Za-z]+)){",n_after,"}"))
             )
    
    
                                Sentence Keyword    Keyword_w_context Keyword_w_context_before Keyword_w_context_after
    1     The yellow lab dog is so cute.     dog   The yellow lab dog       The yellow lab dog               dog is so
    2 The fluffy black cat purrs loudly.     cat The fluffy black cat     The fluffy black cat        cat purrs loudly
    

    【讨论】:

    • 谢谢你,jvargh7。这确实与表中的内容相符。但是,正如我在问题文本中指出的那样,我需要能够将其修改为关键字的 2 个字之前、3 个字之前等。现在,这是在关键字之前提取所有内容。是否有一个简单的编辑来实现这一点?
    • 现在可以试试吗?更改“n”以获得不同的结果
    • 再次感谢您,jvargh7。感谢您抽出宝贵时间帮助我找到解决方案。我无法让代码工作。它适用于某些行,但不适用于其他行。我不明白为什么。再次,我很感激。
    • 没问题@BrianHead。亚当的解决方案要好得多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-01
    • 1970-01-01
    • 2018-03-09
    • 1970-01-01
    • 2017-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多