【问题标题】:what is the most efficient way of counting occurrences in pandas?计算熊猫中出现次数的最有效方法是什么?
【发布时间】:2013-12-03 06:43:22
【问题描述】:

我有一个大的(大约 1200 万行)数据框 df 说:

df.columns = ['word','documents','frequency']

因此,以下内容及时运行:

word_grouping = df[['word','frequency']].groupby('word')
MaxFrequency_perWord = word_grouping[['frequency']].max().reset_index()
MaxFrequency_perWord.columns = ['word','MaxFrequency']

但是,这需要很长时间才能运行:

Occurrences_of_Words = word_grouping[['word']].count().reset_index()

我在这里做错了什么?有没有更好的方法来计算大型数据框中的出现次数?

df.word.describe()

运行得很好,所以我真的没想到这个 Occurrences_of_Words 数据框需要很长时间才能构建。

ps:如果答案很明显,并且您觉得有必要因为我提出这个问题而惩罚我,请同时附上答案。谢谢。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    我认为df['word'].value_counts() 应该发球。通过跳过 groupby 机制,您将节省一些时间。我不确定为什么count 应该比max 慢得多。两者都需要一些时间来避免缺失值。 (与size比较。)

    无论如何,value_counts 一直是specifically optimized 来处理对象类型,就像你说的那样,所以我怀疑你会做得比这更好。

    【讨论】:

    • 谢谢。我还发现这对于加速计算系列中的特定值很有用。例如df.word.value_counts()['myword'] 的速度大约是 len(df[df.word == 'myword']) 的两倍。
    • 计算整个 DataFrame 怎么样?这适用于一列。
    • 回答我自己的问题(想通了):.stack() 函数
    • @Newbielp,我这样做了: df[[i for i in column_names]].astype('str').stack().value_counts().sum() 相当于设置每个选定的列到 str 类型,将所有单独的列堆叠在顶部,基本上形成一列,然后在该列上执行 value_counts() 和 sum()。 :) Stack 非常有用,它可能不是最明显的选择,但对我的用例来说就像一个魅力:)
    • 要添加到@fantabolous 的注释,如果列中可能存在零值,请使用.get() 方法。在这种情况下,.get() 将返回 None,而使用括号方法将引发错误。
    【解决方案2】:

    当你想统计 pandas dataFrame 中某一列中分类数据出现的频率时,请使用:df['Column_Name'].value_counts()

    -Source.

    【讨论】:

      【解决方案3】:

      只是对先前答案的补充。我们不要忘记,在处理真实数据时可能会有空值,因此使用选项dropna=False (default is True) 将这些值也包括在计数中是很有用的

      一个例子:

      >>> df['Embarked'].value_counts(dropna=False)
      S      644
      C      168
      Q       77
      NaN      2
      

      【讨论】:

        【解决方案4】:

        计算出现次数的其他可能方法是使用 (i) Counter from collections module,(ii) unique from numpy library 和 (iii) groupby + size in @987654331 @。

        使用collections.Counter

        from collections import Counter
        out = pd.Series(Counter(df['word']))
        

        使用numpy.unique

        import numpy as np
        i, c = np.unique(df['word'], return_counts = True)
        out = pd.Series(c, index = i)
        

        使用groupby + size

        out = pd.Series(df.index, index=df['word']).groupby(level=0).size()
        

        上述方法中缺少value_counts 的一个非常好的功能是它对计数进行排序。如果对计数进行排序是绝对必要的,那么value_counts 是最好的方法,因为它简单且性能好(尽管它的性能仍略逊于其他方法,尤其是对于非常大的系列)。

        基准

        (如果对计数进行排序并不重要):

        如果我们查看运行时,它取决于存储在 DataFrame 列/系列中的数据。

        如果Series是dtype对象,那么对于非常大的Series最快的方法是collections.Counter,但总的来说value_counts很有竞争力。

        但是,如果是dtype int,那么最快的方法是numpy.unique

        用于生成绘图的代码:

        import perfplot
        import numpy as np
        import pandas as pd
        from collections import Counter
        
        def creator(n, dt='obj'):
            s = pd.Series(np.random.randint(2*n, size=n))
            return s.astype(str) if dt=='obj' else s
            
        def plot_perfplot(datatype):
            perfplot.show(
                setup = lambda n: creator(n, datatype),
                kernels = [lambda s: s.value_counts(),
                           lambda s: pd.Series(Counter(s)),
                           lambda s: pd.Series((ic := np.unique(s, return_counts=True))[1], index = ic[0]),
                           lambda s: pd.Series(s.index, index=s).groupby(level=0).size()
                          ],
                labels = ['value_counts', 'Counter', 'np_unique', 'groupby_size'],
                n_range = [2 ** k for k in range(5, 25)],
                equality_check = lambda *x: (d:= pd.concat(x, axis=1)).eq(d[0], axis=0).all().all(),
                xlabel = '~len(s)',
                title = f'dtype {datatype}'
            )
            
        plot_perfplot('obj')
        plot_perfplot('int')
        

        【讨论】:

          猜你喜欢
          • 2011-01-23
          • 2020-07-24
          • 2022-01-18
          • 2019-02-22
          • 1970-01-01
          • 1970-01-01
          • 2011-07-13
          • 2020-12-04
          相关资源
          最近更新 更多