我有一个有两列的numpy数组:
A = [[1,1,1,2,3,1,2,3],[0.1,0.2,0.2,0.1,0.3,0.2,0.2,0.1]]
对于第一列中的所有唯一身份,我想要与其对应的值的平均值。例如
B = [[1,2,3], [0.175, 0.15, 0.2]]
有没有pythonic的方法来做到这一点?
答案 0 :(得分:4)
我认为以下是这种计算的标准numpy方法。如果np.unique
的条目是小整数,则可以跳过对A[0]
的调用,但它会使整个操作更加健壮并且与实际数据无关。
>>> A = [[1,1,1,2,3,1,2,3],[0.1,0.2,0.2,0.1,0.3,0.2,0.2,0.1]]
>>> unq, unq_idx = np.unique(A[0], return_inverse=True)
>>> unq_sum = np.bincount(unq_idx, weights=A[1])
>>> unq_counts = np.bincount(unq_idx)
>>> unq_avg = unq_sum / unq_counts
>>> unq
array([1, 2, 3])
>>> unq_avg
array([ 0.175, 0.15 , 0.2 ])
当然你可以堆叠两个数组,虽然这会将unq
转换为float dtype:
>>> np.vstack((unq, unq_avg))
array([[ 1. , 2. , 3. ],
[ 0.175, 0.15 , 0.2 ]])
答案 1 :(得分:1)
一种可能的解决方案是:
In [37]: a=np.array([[1,1,1,2,3,1,2,3],[0.1,0.2,0.2,0.1,0.3,0.2,0.2,0.1]])
In [38]: np.array([list(set(a[0])), [np.average(np.compress(a[0]==i, a[1])) for i in set(a[0])]])
Out[38]:
array([[ 1. , 2. , 3. ],
[ 0.175, 0.15 , 0.2 ]])
答案 2 :(得分:1)
您可以使用np.histogram
首先获取与A[1]
中每个唯一索引对应的A[1]
中的值的总和,然后使用import numpy as np
A = np.array([[1,1,1,2,3,1,2,3],[0.1,0.2,0.2,0.1,0.3,0.2,0.2,0.1]])
# NB for n unique values in A[0] we want (n + 1) bin edges, such that
# A[0].max() < bin_edges[-1]
bin_edges = np.arange(A[0].min(), A[0].max()+2, dtype=np.int)
# the `weights` parameter means that the count for each bin is weighted
# by the corresponding value in A[1]
weighted_sums,_ = np.histogram(A[0], bins=bin_edges, weights=A[1])
# by calling `np.histogram` again without the `weights` parameter, we get
# the total number of occurrences of each unique index
index_counts,_ = np.histogram(A[0], bins=bin_edges)
# now just divide the weighted sums by the total occurrences
urow_avg = weighted_sums / index_counts
print urow_avg
# [ 0.175 0.15 0.2 ]
的总出现次数来更有效地执行此操作每个独特的指数。
例如:
{{1}}
答案 3 :(得分:1)
另一个有效的numpy解决方案,使用reduceat:
A=np.array(zip(*[[1,1,1,2,3,1,2,3],[0.1,0.2,0.2,0.1,0.3,0.2,0.2,0.1]]),
dtype=[('id','int64'),('value','float64')])
A.sort(order='id')
unique_ids,idxs = np.unique(A['id'],return_index=True)
avgs = np.add.reduceat(A['value'],idxs)
#divide by the number of samples to obtain the actual averages.
avgs[:-1]/=np.diff(idxs)
avgs[-1]/=A.size-idxs[-1]
答案 4 :(得分:0)
您可以按如下方式处理:
values = {}
# get all values for each index
for index, value in zip(*A):
if index not in values:
values[index] = []
values[index].append(value)
# create average for each index
for index in values:
values[index] = sum(values[index]) / float(len(values[index]))
B = np.array(zip(*values.items()))
对于你的例子,这给了我:
>>> B
array([[ 1. , 2. , 3. ],
[ 0.175, 0.15 , 0.2 ]])
您可以使用collections.defaultdict
轻微简化:
from collections import defaultdict
values = defaultdict(list)
for index, value in zip(*A):
values[index].append(value)