Groupby在python列表中

时间:2016-01-20 17:11:55

标签: python

鉴于有一百万条记录的大型数据集,我正在寻找方法来进行分组。 我是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)

我正在寻找有效的方法,有没有办法在列表理解中做一个groupby?谢谢!

3 个答案:

答案 0 :(得分:3)

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

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()]

答案 1 :(得分:2)

groupby确实存在itertools方法,请注意它需要事先对数据进行排序,请参阅此处的文档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)]

答案 2 :(得分:0)

您可能希望习惯于处理此类数据的电子表格类型界面。这是一个比你要求的更大的实现,但从长远来看,图形和图表将更容易。这个例子使用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