【问题标题】:Conditional word frequency count in PandasPandas 中的条件词频计数
【发布时间】:2020-05-16 06:29:58
【问题描述】:

我有一个如下的数据框:

data = {'speaker':['Adam','Ben','Clair'],
        'speech': ['Thank you very much and good afternoon.',
                   'Let me clarify that because I want to make sure we have got everything right',
                   'By now you should have some good rest']}
df = pd.DataFrame(data)

我想计算语音列中的单词数,但只计算预定义列表中的单词。例如,列表是:

wordlist = ['much', 'good','right']

我想生成一个新列,显示这三个词在每一行中出现的频率。因此,我的预期输出是:

     speaker                   speech                               words
0   Adam          Thank you very much and good afternoon.             2
1   Ben        Let me clarify that because I want to make sur...      1
2   Clair        By now you should have received a copy of our ...    1

我试过了:

df['total'] = 0
for word in df['speech'].str.split():
    if word in wordlist: 
        df['total'] += 1

但我运行它后,total 列始终为零。我想知道我的代码有什么问题?

【问题讨论】:

  • 要了解您的代码有什么问题,您可以从打印循环中的每个单词开始。你会看到你的 word 实际上是一个字符串列表,而不是一个字符串。另外,当你做df['total'] += 1时,你给df.total列的每个元素加1,这不是你想要达到的。
  • @AnnaK。感谢您的解释。我现在确实看到单词是单词列表,而不是单个单词(但我对为什么 jupytyer 在运行“if word in wordlist”时不显示错误感到困惑)。想知道要不要写正确(就是word是单个词),应该怎么写呢?
  • 我喜欢@CDBJ 的回答。您应该尽可能避免在数据帧行上循环。
  • 我理解您的意思,并且以后一定会牢记这一点。但只是出于好奇,如果string.split 不起作用,我怎么能得到每行的单个单词?我一直在寻找它,但没有找到一个好的答案......

标签: python string pandas dataframe nlp


【解决方案1】:

您可以使用以下矢量化方法:

data = {'speaker':['Adam','Ben','Clair'],
        'speech': ['Thank you very much and good afternoon.',
                   'Let me clarify that because I want to make sure we have got everything right',
                   'By now you should have some good rest']}
df = pd.DataFrame(data)

wordlist = ['much', 'good','right']

df['total'] = df['speech'].str.count(r'\b|\b'.join(wordlist))

这给出了:

>>> df
  speaker                                             speech  total
0    Adam            Thank you very much and good afternoon.      2
1     Ben  Let me clarify that because I want to make sur...      1
2   Clair              By now you should have some good rest      1

【讨论】:

  • 非常感谢您的解决方案!我刚刚查看了series.str.count 并在测试样本上运行了您的代码。效果很好!但我想知道你能帮我更好地理解它吗?我有两个问题,1)| 的功能是什么?在括号中(分隔单词列表中的单词?)和2)如何使用.join?如果它们是愚蠢的问题,我深表歉意,但我花了过去一个小时试图自己理解它们,但仍然不知道......
  • '|' 是 pandas 计数函数的缩写。 string.join() 的文档是 here。因此,例如,'|'.join(wordlist) 给了我们'much|good|right',然后计数函数会找到'much' 或'good' 或'right' 在列中出现的次数。
  • 现在我明白了!这样一个整洁而有用的组合。非常感谢!但我可以问另一个问题吗?在@Anna K. 评论中,据说“您应该尽可能避免在数据帧行上循环”。我可以看到string.count() 中没有显式循环,但它是如何工作的?它是否以wordlist 开头并计算每行中每个单词的出现次数,然后总结它们? (与我失败的方法相反,我首先查看每行中的每个单词并检查它是否包含在 wordlist 中,然后对所有匹配的单词求和)。
  • @TaoHan 这种方法应用了矢量化方法——这意味着操作是一次批量应用到每一列,而不是一个接一个。这比逐行循环更有效,但在 Pandas C 扩展中是在低级别完成的,通常不能应用于普通的 python 数据结构。您可以在这个问题中阅读更多内容:stackoverflow.com/q/35091979/12366110
  • 我终于想通了。我认为这与使用| 分隔wordlist 有关。如果我将代码更改为str.count(r'\b|\b'.join(wordlist))(计算单个单词),结果似乎是正确的。 @CDJB
【解决方案2】:
import pandas as pd

data = {'speaker': ['Adam', 'Ben', 'Clair'],
        'speech': ['Thank you very much and good afternoon.',
                   'Let me clarify that because I want to make sure we have got everything right',
                   'By now you should have some good rest']}
df = pd.DataFrame(data)

wordlist = ['much', 'good', 'right']

df["speech"] = df["speech"].str.split()
df = df.explode("speech")
counts = df[df.speech.isin(wordlist)].groupby("speaker").size()
print(counts)

【讨论】:

  • 谢谢! @亚历克斯大厅。我试过你的方法,它也有效(我从未想过的新方法)!但我想知道 1)是否有可能“爆炸”它?我将使用数据进行额外的分析,因此数据帧保持在语音级别(每行一个语音)和 2)我如何创建一个包含计数的新列?我试过df['counts'] = df[df.speech.isin(wordlist)].groupby("speaker").size() 并希望对同一个扬声器有相同的值,但整个“计数”列的值都丢失了。
【解决方案3】:

如果您有一个非常大的列表和一个大数据框要搜索,这是一个更快(运行时)的解决方案。

我猜这是因为它利用了字典(需要 O(N) 来构建和 O(1) 来搜索)。性能方面,正则表达式搜索速度较慢。

import pandas as pd
from collections import Counter

def occurrence_counter(target_string, search_list):
    data = dict(Counter(target_string.split()))
    count = 0
    for key in search_list:
        if key in data:
            count+=data[key]
    return count

data = {'speaker':['Adam','Ben','Clair'],
        'speech': ['Thank you very much and good afternoon.',
                   'Let me clarify that because I want to make sure we have got everything right',
                   'By now you should have some good rest']}
df = pd.DataFrame(data)

wordlist = ['much', 'good','right']

df['speech'].apply(lambda x: occurrence_counter(x, wordlist))

【讨论】:

  • 确实,我同意这个解决方案。
猜你喜欢
  • 2017-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-16
  • 1970-01-01
相关资源
最近更新 更多