分组和平均 NumPy 矩阵

Posted

技术标签:

【中文标题】分组和平均 NumPy 矩阵【英文标题】:Group and average NumPy matrix 【发布时间】:2015-05-31 05:25:31 【问题描述】:

假设我有一个如下所示的任意 numpy 矩阵:

arr = [[  6.0   12.0   1.0]
       [  7.0   9.0   1.0]
       [  8.0   7.0   1.0]
       [  4.0   3.0   2.0]
       [  6.0   1.0   2.0]
       [  2.0   5.0   2.0]
       [  9.0   4.0   3.0]
       [  2.0   1.0   4.0]
       [  8.0   4.0   4.0]
       [  3.0   5.0   4.0]]

对按第三列编号分组的行进行平均的有效方法是什么?

预期的输出是:

result = [[  7.0  9.33  1.0]
          [  4.0  3.0  2.0]
          [  9.0  4.0  3.0]
          [  4.33  3.33  4.0]]

【问题讨论】:

只使用 numpy 而没有循环 ***.com/a/66871328/10375049 【参考方案1】:

一个紧凑的解决方案是使用numpy_indexed(免责声明:我是它的作者),它实现了一个完全矢量化的解决方案:

import numpy_indexed as npi
npi.group_by(arr[:, 2]).mean(arr)

【讨论】:

【参考方案2】:
arr = np.array(
[[  6.0,   12.0,   1.0],
 [  7.0,   9.0,   1.0],
 [  8.0,   7.0,   1.0],
 [  4.0,   3.0,   2.0],
 [  6.0,   1.0,   2.0],
 [  2.0,   5.0,   2.0],
 [  9.0,   4.0,   3.0],
 [  2.0,   1.0,   4.0],
 [  8.0,   4.0,   4.0],
 [  3.0,   5.0,   4.0]])
np.array([a.mean(0) for a in np.split(arr, np.argwhere(np.diff(arr[:, 2])) + 1)])

【讨论】:

【参考方案3】:

解决方案

from itertools import groupby
from operator import itemgetter

arr = [[6.0, 12.0, 1.0],
       [7.0, 9.0, 1.0],
       [8.0, 7.0, 1.0],
       [4.0, 3.0, 2.0],
       [6.0, 1.0, 2.0],
       [2.0, 5.0, 2.0],
       [9.0, 4.0, 3.0],
       [2.0, 1.0, 4.0],
       [8.0, 4.0, 4.0],
       [3.0, 5.0, 4.0]]

result = []

for groupByID, rows in groupby(arr, key=itemgetter(2)):
    position1, position2, counter = 0, 0, 0
    for row in rows:
        position1+=row[0]
        position2+=row[1]
        counter+=1
    result.append([position1/counter, position2/counter, groupByID])

print(result)

会输出:

[[7.0, 9.333333333333334, 1.0]]
[[4.0, 3.0, 2.0]]
[[9.0, 4.0, 3.0]]
[[4.333333333333333, 3.3333333333333335, 4.0]]

【讨论】:

【参考方案4】:

你可以这样做:

for x in sorted(np.unique(arr[...,2])):
    results.append([np.average(arr[np.where(arr[...,2]==x)][...,0]), 
                    np.average(arr[np.where(arr[...,2]==x)][...,1]),
                    x])

测试:

>>> arr
array([[  6.,  12.,   1.],
       [  7.,   9.,   1.],
       [  8.,   7.,   1.],
       [  4.,   3.,   2.],
       [  6.,   1.,   2.],
       [  2.,   5.,   2.],
       [  9.,   4.,   3.],
       [  2.,   1.,   4.],
       [  8.,   4.,   4.],
       [  3.,   5.,   4.]])
>>> results=[]
>>> for x in sorted(np.unique(arr[...,2])):
...     results.append([np.average(arr[np.where(arr[...,2]==x)][...,0]), 
...                     np.average(arr[np.where(arr[...,2]==x)][...,1]),
...                     x])
... 
>>> results
[[7.0, 9.3333333333333339, 1.0], [4.0, 3.0, 2.0], [9.0, 4.0, 3.0], [4.333333333333333, 3.3333333333333335, 4.0]]

数组arr不需要排序,所有中间数组都是视图(即不是新的数据数组)。平均值是直接根据这些视图有效计算的。

【讨论】:

我喜欢,很干净。我将如何将结果存储到 numpy.array 中? 我发现最简单的方法是将结果转换为任何给定的类型。所以我有results = np.asarray(results),输出很完美。

以上是关于分组和平均 NumPy 矩阵的主要内容,如果未能解决你的问题,请参考以下文章

计算 Numpy 矩阵中每一行的平均值

如何计算按列名分组的数据框/矩阵中的平均值和标准差

Numpy

使用 NumPy 函数计算 Pandas 中的加权平均值

矩阵乘法中每个单元格的平均值,而不仅仅是 python 中的总和

pandas 学习 第4篇:序列的处理(应用聚合转换映射分组滚动扩展指数加权移动平均)