【问题标题】:Counting the Frequency of words in a pandas data frame计算熊猫数据框中单词的频率
【发布时间】:2018-03-28 21:54:44
【问题描述】:

我有一张如下表:

      URN                   Firm_Name
0  104472               R.X. Yah & Co
1  104873        Big Building Society
2  109986          St James's Society
3  114058  The Kensington Society Ltd
4  113438      MMV Oil Associates Ltd

我想计算 Firm_Name 列中所有单词的频率,以获得如下输出:

我试过下面的代码:

import pandas as pd
import nltk
data = pd.read_csv("X:\Firm_Data.csv")
top_N = 20
word_dist = nltk.FreqDist(data['Firm_Name'])
print('All frequencies')
print('='*60)
rslt=pd.DataFrame(word_dist.most_common(top_N),columns=['Word','Frequency'])

print(rslt)
print ('='*60)

但是,以下代码不会产生唯一字数。

【问题讨论】:

    标签: python pandas nltk


    【解决方案1】:

    IIUIC,使用value_counts()

    In [3361]: df.Firm_Name.str.split(expand=True).stack().value_counts()
    Out[3361]:
    Society       3
    Ltd           2
    James's       1
    R.X.          1
    Yah           1
    Associates    1
    St            1
    Kensington    1
    MMV           1
    Big           1
    &             1
    The           1
    Co            1
    Oil           1
    Building      1
    dtype: int64
    

    或者,

    pd.Series(np.concatenate([x.split() for x in df.Firm_Name])).value_counts()
    

    或者,

    pd.Series(' '.join(df.Firm_Name).split()).value_counts()
    

    对于前 N 个,例如 3

    In [3379]: pd.Series(' '.join(df.Firm_Name).split()).value_counts()[:3]
    Out[3379]:
    Society    3
    Ltd        2
    James's    1
    dtype: int64
    

    详情

    In [3380]: df
    Out[3380]:
          URN                   Firm_Name
    0  104472               R.X. Yah & Co
    1  104873        Big Building Society
    2  109986          St James's Society
    3  114058  The Kensington Society Ltd
    4  113438      MMV Oil Associates Ltd
    

    【讨论】:

    • 我一定会接受你的回答。我正在等待以挤奶开放答案方面。
    • .split(expand=True).stack() 是处理小数据的一个非常聪明的选择,但是对于任何大小的数据,它都会很快耗尽内存。由于它为Firm_Name 中的每个唯一单词扩展了一个矩阵,因此数据稀疏性会在没有太多观察的情况下爆炸矩阵列。
    • 谢谢。如果我只想每行每个单词第一次出现怎么办?如何消除同一行中相同单词的重复?
    • 如前所述,如果您的字符串数据是可变长度的,.split(expand=True).stack().value_counts() 会占用大量内存。试试这个.str.split().explode().value_counts()。它在不分配任何额外内存的情况下执行完全相同的操作。
    • 我测试了所有这三种方法的速度,以及@WilliamGerecke 评论中列出的第四个选项 (.explode())。我的 df 有 500k 行,每行包含 0 到 400 个单词。结果四舍五入到最接近的秒数是:df.Firm_Name.str.split(expand=True).stack().value_counts() - 77 秒 pd.Series(np.concatenate([x.split() for x in df.Firm_Name])).value_counts() - 24 pd.Series(' '.join(df.Firm_Name).split()).value_counts() - 4 df.Firm_Name.str.split().explode().value_counts() - 6。
    【解决方案2】:

    您首先需要str.catlower 将所有值连接到一个string,然后需要word_tokenize,最后使用您的解决方案:

    top_N = 4
    #if not necessary all lower
    a = data['Firm_Name'].str.lower().str.cat(sep=' ')
    words = nltk.tokenize.word_tokenize(a)
    word_dist = nltk.FreqDist(words)
    print (word_dist)
    <FreqDist with 17 samples and 20 outcomes>
    
    rslt = pd.DataFrame(word_dist.most_common(top_N),
                        columns=['Word', 'Frequency'])
    print(rslt)
          Word  Frequency
    0  society          3
    1      ltd          2
    2      the          1
    3       co          1
    

    如有必要,也可以删除lower

    top_N = 4
    a = data['Firm_Name'].str.cat(sep=' ')
    words = nltk.tokenize.word_tokenize(a)
    word_dist = nltk.FreqDist(words)
    rslt = pd.DataFrame(word_dist.most_common(top_N),
                        columns=['Word', 'Frequency'])
    print(rslt)
             Word  Frequency
    0     Society          3
    1         Ltd          2
    2         MMV          1
    3  Kensington          1
    

    【讨论】:

    • 非常感谢伟大的解决方案
    • 是的,接受什么答案取决于您。两种解决方案都有效 - 零解决方案是纯熊猫和我的纯 ntlk。而且我猜应该会有一些小的差异,ntlkword_tokenize中的数据有点变化。
    【解决方案3】:

    这个答案也可以使用 - Count distinct words from a Pandas Data Frame。它利用 Counter 方法并将其应用于每一行。

    from collections import Counter
    c = Counter()
    df = pd.DataFrame(
        [[104472,"R.X. Yah & Co"],
        [104873,"Big Building Society"],
        [109986,"St James's Society"],
        [114058,"The Kensington Society Ltd"],
        [113438,"MMV Oil Associates Ltd"]
    ], columns=["URN","Firm_Name"])
    df.Firm_Name.str.split().apply(c.update)
    
    Counter({'R.X.': 1,
             'Yah': 1,
             '&': 1,
             'Co': 1,
             'Big': 1,
             'Building': 1,
             'Society': 3,
             'St': 1,
             "James's": 1,
             'The': 1,
             'Kensington': 1,
             'Ltd': 2,
             'MMV': 1,
             'Oil': 1,
             'Associates': 1})
    

    【讨论】:

      猜你喜欢
      • 2022-01-18
      • 2019-11-27
      • 1970-01-01
      • 2016-05-20
      • 1970-01-01
      • 2020-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多