首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从python Numpy数组中操作数据:使用一列中的值对相邻值求和

问从python Numpy数组中操作数据:使用一列中的值对相邻值求和
EN

Stack Overflow用户
提问于 2014-02-03 08:38:44
回答 5查看 526关注 0票数 1

下面是我的数据:

代码语言:javascript
复制
a = np.array([[1,2],[2,1],[7,1],[3,2]])

我想对这里第二行的每个数字求和。因此,在本例中,第二列中有两个可能的值:1和2。

我想对第一列中所有在第二列中具有相同值的值求和。有没有内置的numpy函数呢?

例如,第二列中每个1的总和为:2+7=9

EN

回答 5

Stack Overflow用户

发布于 2014-02-03 09:03:42

一种简短但有点不可靠的方法是通过numpy函数bincount:

代码语言:javascript
复制
np.bincount(a[:,1], weights=a[:,0])

它所做的是计算数组中0、1、2等的出现次数(在本例中,a[:,1]是您的类别编号列表)。现在,weights将计数乘以一些权重,在本例中,权重是列表中的第一个值,本质上是以这种方式计算总和。

它返回的是:

代码语言:javascript
复制
array([ 0.,  9.,  4.])

其中0是第一个元素的总和,第二个元素是0,依此类推...因此,只有当你分组的第二个数字是整数时,它才会起作用。

如果它们不是从0开始的连续整数,您可以通过执行以下操作来选择需要的整数:

代码语言:javascript
复制
np.bincount(a[:,1], weights=a[:,0])[np.unique(a[:,1])]

这将返回

代码语言:javascript
复制
array([9.,  4.])

它是一个和数组,按第二个元素排序(因为unique返回一个排序列表)。

如果你的第二个元素不是整数,首先你会遇到一些麻烦,因为floating point arithmetic (你认为相等的元素实际上可能是不同的)。但是,如果确定没有问题,可以对它们进行排序并将整数赋值给它们(例如,使用scipy的rank函数):

代码语言:javascript
复制
ind = rd(a[:,1], method = 'dense').astype(int) - 1 # ranking begins from 1, we need from 0
sums = np.bincount(ind, weights=a[:,0])

这将返回array([9., 4.]),按您的第二个元素排序。您可以将它们压缩为具有适当元素的配对求和:

代码语言:javascript
复制
zip(np.unique(a[:,1]), sums) 
票数 2
EN

Stack Overflow用户

发布于 2014-02-03 10:26:14

play.py的内容

代码语言:javascript
复制
import numpy as np

def compute_sum1(a):
    unique = np.unique(a[:, 1])
    same_idxs = ((u, np.argwhere(a[:, 1] == u)) for u in unique)
    # First coordinate of tuple contains value of col 2
    # Second coordinate contains the sum of entries from col 1
    same_sum = [(u, np.sum(a[idx, 0])) for u, idx in same_idxs]
    return same_sum

def compute_sum2(a):
    """A minimal implementation of compute_sum"""
    unique = np.unique(a[:, 1])
    same_idxs = (np.argwhere(a[:, 1] == u) for u in unique)
    same_sum = (np.sum(a[idx, 0]) for idx in same_idxs)
    return same_sum

def compute_sum3(a):
    unique = np.unique(a[:, 1])
    same_idxs = [np.argwhere(a[:, 1] == u) for u in unique]
    same_sum = np.sum(a[same_idxs, 0].squeeze(), 1)
    return same_sum

def main():
    a = np.array([[1,2],[2,1],[7,1],[3,2]]).astype("float")
    print("compute_sum1")
    print(compute_sum1(a))
    print("compute_sum3")
    print(compute_sum3(a))
    print("compute_sum2")
    same_sum = [s for s in compute_sum2(a)]
    print(same_sum)


if __name__ == '__main__':
    main()

输出:

代码语言:javascript
复制
In [59]: play.main()
compute_sum1
[(1.0, 9.0), (2.0, 4.0)]
compute_sum3
[ 9.  4.]
compute_sum2
[9.0, 4.0]

In [60]: %timeit play.compute_sum1(a)
10000 loops, best of 3: 95 µs per loop

In [61]: %timeit play.compute_sum2(a)
100000 loops, best of 3: 14.1 µs per loop

In [62]: %timeit play.compute_sum3(a)
10000 loops, best of 3: 77.4 µs per loop

请注意,compute_sum2()是最快的。如果您的矩阵很大,我建议使用此实现,因为它使用生成器理解而不是列表理解,后者更有效地利用内存。类似地,compute_sum1()中的same_sum可以通过将[]替换为()来转换为生成器理解。

票数 2
EN

Stack Overflow用户

发布于 2014-02-03 11:17:00

您可能想看看这个库:https://github.com/ml31415/accumarray。它是来自matlabs accumarray for numpy的克隆。

代码语言:javascript
复制
a = np.array([[1,2],[2,1],[7,1],[3,2]])
accum(a[:,1], a[:,0])
>>> array([0, 9, 4])

第一个0表示在索引列中没有带0的字段。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21518186

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档