【问题标题】:python word grouping based on words before and after基于前后单词的python单词分组
【发布时间】:2023-11-07 09:23:01
【问题描述】:

我正在尝试创建单词组。首先,我计算所有单词。然后我按字数确定前 10 个字。然后我想根据前 10 个单词创建 10 组单词。每组由位于最上面的单词之前和之后的所有单词组成。

我将调查结果存储在一个像这样结构的 python pandas 数据框中

Question_ID | Customer_ID | Answer
  1           234         Data is very important to use because ... 
  2           234         We value data since we need it ... 

我还将答案列保存为字符串。

我正在使用以下代码在一个单词之前和之后查找 3 个单词(实际上我必须从答案列中创建一个字符串)

answers_str = df.Answer.apply(str)
for value in answers_str:
   non_data = re.split('data|Data', value)
   terms_list = [term for term in non_data if len(term) > 0] # skip empty terms
   substrs = [term.split()[0:3] for term in terms_list]  # slice and grab first three terms
   result = [' '.join(term) for term in substrs] # combine the terms back into substrings
   print result

我一直在手动创建单词组 - 但是有没有办法在 python 中做到这一点?

因此,根据上面显示的示例,包含字数的组将如下所示:

group "data": 
              data : 2
              important: 1
              value: 1
              need:1

那么当它遍历整个文件时,就会有另一个组:

group "analytics:
              analyze: 5
              report: 7
              list: 10
              visualize: 16

我们的想法是去掉“we”、“to”、“is”——但如果不可能的话,我可以手动完成。

然后建立 10 个最常用的单词(按字数计算),然后创建 10 个组,其中单词位于前 10 个主要单词的前面和后面。

【问题讨论】:

    标签: python string pandas grouping


    【解决方案1】:

    我们可以为此使用正则表达式。我们将使用这个正则表达式

    ((?:\b\w+?\b\s*){0,3})[dD]ata((?:\s*\b\w+?\b){0,3})
    

    你可以自己测试here,提取每次数据出现前后的三个词

    首先,让我们从字符串中删除所有我们不喜欢的单词。

    import re
    
    #    If you're processing a lot of sentences, it's probably wise to preprocess
    #the pattern, assuming that bad_words is the same for all sentences
    def remove_words(sentence, bad_words):
        pat = r'(?:{})'.format(r'|'.join(bad_words))
        return re.sub(pat, '', sentence, flags=re.IGNORECASE)
    

    我们想要获取每行数据周围的单词

    data_pat = r'((?:\b\w+?\b\s*){0,3})[dD]ata((?:\s*\b\w+?\b){0,3})'
    res = re.findall(pat, s, flags=re.IGNORECASE)
    

    给我们一个字符串元组的列表。我们希望在它们被拆分后得到这些字符串的列表。

    from itertools import chain
    list_of_words = list(chain.from_iterable(map(str.split, chain.from_iterable(map(chain, chain(res))))))
    

    这并不漂亮,但它有效。基本上,我们将元组从列表中拉出,从每个元组中拉出字符串,然后拆分每个字符串,然后将所有字符串从它们最终进入的列表中拉出,形成一个大列表。

    让我们将这些与您的pandas 代码放在一起。 pandas 不是我最擅长的领域,所以如果你看到一些奇怪的东西,请不要以为我没有犯一些基本的错误。

    import re
    from itertools import chain
    from collections import Counter    
    
    def remove_words(sentence, bad_words):
        pat = r'(?:{})'.format(r'|'.join(bad_words))
        return re.sub(pat, '', sentence, flags=re.IGNORECASE)
    
    bad_words = ['we', 'is', 'to']
    sentence_list = df.Answer.apply(lambda x: remove_words(str(x), bad_words))
    c = Counter()
    data_pat = r'((?:\b\w+?\b\s*){0,3})data((?:\s*\b\w+?\b){0,3})'
    for sentence in sentence_list:
        res = re.findall(data_pat, sentence, flags=re.IGNORECASE)
        words = chain.from_iterable(map(str.split, chain.from_iterable(map(chain, chain(res)))))
        c.update(words)
    

    我们使用的正则表达式的好处是所有复杂的部分都不关心我们使用的是什么词。稍作改动,我们可以制作一个格式字符串

    base_pat = r'((?:\b\w+?\b\s*){{0,3}}){}((?:\s*\b\w+?\b){{0,3}})'
    

    这样

    base_pat.format('data') == data_pat
    

    所以我们想通过一些单词列表来收集关于key_words的信息

    import re
    from itertools import chain
    from collections import Counter    
    
    def remove_words(sentence, bad_words):
        pat = r'(?:{})'.format(r'|'.join(bad_words))
        return re.sub(pat, '', sentence, flags=re.IGNORECASE)
    
    
    bad_words = ['we', 'is', 'to']
    
    sentence_list = df.Answer.apply(lambda x: remove_words(str(x), bad_words))
    
    key_words = ['data', 'analytics']
    d = {}
    
    base_pat = r'((?:\b\w+?\b\s*){{0,3}}){}((?:\s*\b\w+?\b){{0,3}})'
    for keyword in key_words:
        key_pat = base_pat.format(keyword)
        c = Counter()
        for sentence in sentence_list:
            res = re.findall(key_pat, sentence, flags=re.IGNORECASE)
            words = chain.from_iterable(map(str.split, chain.from_iterable(map(chain, chain(res)))))
            c.update(words)
        d[keyword] = c
    

    现在我们有一个字典 d 映射关键字,例如 dataanalyticsCounters 将不在我们黑名单上的单词映射到相关关键字附近的计数。像

    d= {'data'      : Counter({ 'important' : 2,
                                'very'      : 3}),
        'analytics' : Counter({ 'boring'    : 5,
                                'sleep'     : 3})
       }
    

    至于我们如何获得前 10 个单词,这基本上是 Counter 最擅长的。

    key_words, _ = zip(*Counter(w for sentence in sentence_list for w in sentence.split()).most_common(10))
    

    【讨论】:

    • 非常感谢;使用我创建的字符串而不是 pandas 数据框会更容易吗? answers_str = df.Answer.apply(str)
    • 我收到一条错误消息 SyntaxError: invalid syntax 和一个指向“单词”中 s 的箭头
    • @jeangelj 我搞砸了我的复制粘贴,所以缺少括号。我编辑了它,所以它现在应该可以工作了
    • 谢谢,我收到一条removewords需要2个参数的错误信息,所以我添加了bad_words,然后我收到一条错误信息“pat”未定义;接下来我收到一条错误消息,“s”未定义,s 应该是句子吗?
    • @jeangelj 是的,这就是您将代码分成小块原型时发生的情况。我想我得到了这通行证的一切