我想做一个很好的函数来聚合数组之间的数据(它是一个numpy记录数组,但它没有改变任何东西)
您有一组要在一个轴之间聚合的数据:例如dtype=[(name, (np.str_,8), (job, (np.str_,8), (income, np.uint32)]
的数组,并且您希望获得每个作业的平均收入
我做了这个功能,在示例中它应该被称为aggregate(data,'job','income',mean)
def aggregate(data, key, value, func):
data_per_key = {}
for k,v in zip(data[key], data[value]):
if k not in data_per_key.keys():
data_per_key[k]=[]
data_per_key[k].append(v)
return [(k,func(data_per_key[k])) for k in data_per_key.keys()]
问题是我发现它不是很好我想把它放在一行:你有什么想法吗?
感谢您的回答路易斯
PS:我想在通话中保留func,这样你也可以要求中位数,最小...
答案 0 :(得分:5)
您的if k not in data_per_key.keys()
可以重写为if k not in data_per_key
,但您可以使用defaultdict
做得更好。这是一个使用defaultdict
来摆脱存在检查的版本:
import collections
def aggregate(data, key, value, func):
data_per_key = collections.defaultdict(list)
for k,v in zip(data[key], data[value]):
data_per_key[k].append(v)
return [(k,func(data_per_key[k])) for k in data_per_key.keys()]
答案 1 :(得分:5)
也许您正在寻找的功能是matplotlib.mlab.rec_groupby:
import matplotlib.mlab
data=np.array(
[('Aaron','Digger',1),
('Bill','Planter',2),
('Carl','Waterer',3),
('Darlene','Planter',3),
('Earl','Digger',7)],
dtype=[('name', np.str_,8), ('job', np.str_,8), ('income', np.uint32)])
result=matplotlib.mlab.rec_groupby(data, ('job',), (('income',np.mean,'avg_income'),))
产量
('Digger', 4.0)
('Planter', 2.5)
('Waterer', 3.0)
matplotlib.mlab.rec_groupby
返回一个重新排列:
print(result.dtype)
# [('job', '|S7'), ('avg_income', '<f8')]
您可能还有兴趣查看pandas,其more versatile facilities处理group-by operations。
答案 2 :(得分:2)
Here是一个很好地模仿matlabs accumarray功能的配方。它使用pythons迭代器非常好,但是,与matlab实现相比,它在性能方面很糟糕。由于我遇到同样的问题,我使用scipy.weave
编写了一个实现。您可以在此处找到它:https://github.com/ml31415/accumarray
答案 3 :(得分:2)
使用pandas:
可获得最佳的灵活性和可读性import pandas
data=np.array(
[('Aaron','Digger',1),
('Bill','Planter',2),
('Carl','Waterer',3),
('Darlene','Planter',3),
('Earl','Digger',7)],
dtype=[('name', np.str_,8), ('job', np.str_,8), ('income', np.uint32)])
df = pandas.DataFrame(data)
result = df.groupby('job').mean()
收益率:
income
job
Digger 4.0
Planter 2.5
Waterer 3.0
Pandas DataFrame是一个很棒的课程,但您可以根据需要获得结果:
result.to_records()
result.to_dict()
result.to_csv()
等等......
答案 4 :(得分:2)
使用ndimage.mean中的scipy获得最佳效果。对于这个小数据集,这将比接受的答案快两倍,对于较大的输入,这将快约3.5倍:
map(x -> length(x), a)
49455-element Array{Int64,1}:
1
4
8
.
.
2
将屈服于:
from scipy import ndimage
data=np.array(
[('Aaron','Digger',1),
('Bill','Planter',2),
('Carl','Waterer',3),
('Darlene','Planter',3),
('Earl','Digger',7)],
dtype=[('name', np.str_,8), ('job', np.str_,8), ('income', np.uint32)])
unique = np.unique(data['job'])
result=np.dstack([unique, ndimage.mean(data['income'], data['job'], unique)])
这比小型示例输入的接受答案快约5倍,如果重复数据100000次,速度将提高约8.5倍:
array([[['Digger', '4.0'],
['Planter', '2.5'],
['Waterer', '3.0']]],
dtype='|S32')
答案 5 :(得分:0)
http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#dictionary-get-method
应该有助于使它更漂亮,更pythonic,更有效。我稍后会回来检查你的进度。也许你可以编辑这个功能吗?另见几节。