我想阅读具有以下结构的文件:
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做到这一点?
答案 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已排序。想法:
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)