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