numpy sum几列

时间:2018-06-05 17:40:59

标签: python numpy

我想阅读具有以下结构的文件:

1         3      7        34
1         4      3         6
1         8      2        10
2         9     35        11
2        10     12        24
...

列数从一个文件更改为另一个文件,我想将列的所有值相加为1,2等

所以结果应该是

1       15     12      50
2       19     37      45
...

我开始编写类似的内容:

import numpy as np
import sys

inFile = sys.argv[1]

A = np.genfromtxt(inFile, delimiter=None)

a = np.size(A,1) #get the number of columns

i = np.nonzero(np.diff(A[:, 0]))[0] + 1
i = np.insert(i, 0, 0)

c1 = A[i, 0]
for l in range(3,a+1):
    c = np.add.reduceat(A[:, l], i)
    result = np.c_[c1, c]

我怎么能用numpy做到这一点?

2 个答案:

答案 0 :(得分:2)

Loopy numpy方法

这不是最美丽的方式,并且可能有一种更加优雅和高效的矢量化方法,但您可以通过列表理解来执行以下操作。请参见底部的基准。

给定2-d数组x

>>> x
array([[ 1,  3,  7, 34],
       [ 1,  4,  3,  6],
       [ 1,  8,  2, 10],
       [ 2,  9, 35, 11],
       [ 2, 10, 12, 24]])


np.vstack([np.insert(x[x[:,0] == i][:,1:].sum(axis=0),0,i)
           for i in np.unique(x[:,0])])

返回:

array([[ 1, 15, 12, 50],
       [ 2, 19, 47, 35]])

pandas建议

但是,对于这种表格数据,您可能需要考虑pandas。例如:

import pandas as pd

df = pd.DataFrame(x)

>>> df
   0   1   2   3
0  1   3   7  34
1  1   4   3   6
2  1   8   2  10
3  2   9  35  11
4  2  10  12  24


>>> df.groupby(0).sum()

    1   2   3
0            
1  15  12  50
2  19  47  35

您也可以轻松地将其恢复为numpy数组:

>>> df.groupby(0).sum().reset_index().values
array([[ 1, 15, 12, 50],
       [ 2, 19, 47, 35]])

<强>基准

令我惊讶的是,这两种方法在速度方面具有可比性,我的循环numpy方法在pandas方法上勉强超越:在大型(100000, 100)数组上,循环{ {1}}方法平均花费大约0.1秒,numpy方法平均花费大约0.13秒

pandas

答案 1 :(得分:1)

这是一个完全向量化的方法,假设ID已排序。想法:

  1. 计算整个数据集的cumsum。
  2. 取每个ID的最后一行。
  3. 区分连续的ID。
  4. 重新索引。
  5. def tally(xs):
        # index of the last id in each group
        id_ix = np.searchsorted(xs[:, 0], np.unique(xs[:, 0]), "right") - 1
        # compute cumulative sum over all ids;
        # drop every line that is not final for some id
        csums = xs.cumsum(0)[id_ix]
        # take differences between adjacent groups
        csums[1:] = np.diff(csums, axis=0)
        # recover old IDs
        csums[:, 0] = xs[id_ix, 0]
        return csums
    
    # ys.shape == (1_000_000, 10)
    # In [377]: %timeit q.np_method(q.ys)
    # 5.74 s ± 47.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    
    # In [378]: %timeit q.tally(q.ys)
    # 143 ms ± 1.9 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)