【问题标题】:Groupby in a list for pythonGroupby 在 python 的列表中
【发布时间】:2016-01-20 17:11:54
【问题描述】:

鉴于拥有一百万条记录的大型数据集,我正在寻找分组依据的方法。 我是 python 新手,但我知道在 SQL 中有一个 groupby 函数,我猜它可能适用。

我想要达到的是这个,

来自

["A", 4]
["B", 4]
["F", 3]
["A", 4]
["B", 1]

["A", (4,4)]
["B", (1,4)]
["F", (3)] 

我也在寻找一种有效的方法来计算评分列表的平均值。所以最后的输出应该是:

["A", 4]
["B", 2.5]
["F", 3]

我尝试对其进行迭代处理,但抛出的错误是“要解压的数据太多”。这是我的解决方案,不适用于数据集。

len = max(key for (item, key) in results)
newList = [[] for i in range(len+1)]
for item, key in results: 
    newList[key].append(item)

我正在寻找有效的方法,有没有办法在列表理解中进行分组?谢谢!

【问题讨论】:

  • 该错误表示您的数据集不是格式为[(x, y), ...]。你确定results(x, y) 对的可迭代对象吗?

标签: python


【解决方案1】:

我认为以下对于小型数据集来说是一种合理的方法。

from collections import defaultdict

ls = [
    ["A", 4],
    ["B", 4],
    ["F", 3],
    ["A", 4],
    ["B", 1],
]

d = defaultdict(list)
for key, val in ls:
        d[key].append(val)

# Prints [['A', (4, 4)], ['B', (4, 1)], ['F', (3,)]]
print [[k, tuple(l)] for k, l in d.items()]   

# prints [['A', 4.0], ['B', 2.5], ['F', 3.0]]  
print [[k, float(sum(l))/len(l)] for k, l in d.items()] #*

*在 Python 2.x 中,使用 iteritems() 而不是 items(),请参阅 this answer

稍微好一点,如果您只关心平均值,则不需要存储键映射到的所有内容:

d = defaultdict(lambda: (0, 0))
for key, val in ls:
    cnt, total = d[key]
    d[key] = (cnt + 1, total + val)

print [[k, float(total) / cnt] for k, (cnt, total) in d.items()]

【讨论】:

    【解决方案2】:

    itertools中确实有一个groupby方法,只是需要注意它需要预先对数据进行排序,看这里的文档https://docs.python.org/2/library/itertools.html#itertools.groupby

    但是从您发布的代码来看,您似乎不需要分组,您只想数数,对吗?那么你最好使用collections.Counter。请注意,它要求项目是可散列的,因此您需要将这些列表转换为元组。

    >>> lst = [tuple(i) for i in ls]
    >>> collections.Counter(lst)
    Counter({('A', 4): 2, ('F', 3): 1, ('B', 1): 1, ('B', 4): 1})
    

    关于效率...不确定将整个数据集加载到内存中是否会很好,但您可以使用 Vlad 描述的带有迭代器的 defaultdict 方法。

    关于平均值,如果你真的想使用groupby,那么你可以这样做:

    >>> def average(lst):
    ...     return 1.0*sum(lst)/len(lst) if lst else 0.0
    >>> [(i[0],average([j[1] for j in i[1]])) for i in itertools.groupby(sorted(ls),key=lambda i:i[0])]
    [('A', 4.0), ('B', 2.5), ('F', 3.0)]
    

    【讨论】:

      【解决方案3】:

      您可能希望习惯于处理此类数据的电子表格类型界面。这是一个比您要求的更大的实现,但从长远来看,图形和图表会更容易。此示例使用 pandas 和 numpy。

      突出显示该问题的数据并复制:

      name value
      A 4
      B 4
      F 3
      A 4
      B 1
      

      您可以进入 ipython 并开始输入此操作的设置。

      import pandas as pd
      import numpy as np
      
      data= pd.from_clipboard() 
      

      现在是有趣的部分。 您可以使用数据透视表,它可以按您想要的任何功能对所有这些值进行分组。

      pd.pivot_table(data=data, index='name', aggfunc=np.mean)
      

      返回

            value
      name       
      A       4.0
      B       2.5
      F       3.0
      

      【讨论】:

        猜你喜欢
        • 2015-12-15
        • 1970-01-01
        • 1970-01-01
        • 2012-01-04
        • 2015-05-04
        • 1970-01-01
        • 1970-01-01
        • 2019-09-06
        • 2018-09-01
        相关资源
        最近更新 更多