Ant*_*nin 8 python arrays numpy max vectorization
我有值的阵列,所述v(例如v=[1,2,3,4,5,6,7,8,9,10])和索引的阵列,说g(例如 g=[0,0,0,0,1,1,1,1,2,2]).
我知道,例如,如何以非常简单的方式采取每个组的第一个元素:
import numpy as np
v=np.array([1,2,3,4,74,73,72,71,9,10])
g=np.array([0,0,0,0,1,1,1,1,2,2])
mask=np.concatenate(([True],np.diff(g)!=0))
v[mask]
Run Code Online (Sandbox Code Playgroud)
收益:
array([1, 74, 9])
Run Code Online (Sandbox Code Playgroud)
是否有任何numpythonic方式(避免显式循环)来获得每个子集的最大值?
因为我收到了两个很好的答案,一个是python map,一个是numpy例程,我正在搜索性能最好的,这里有一些时间测试:
import numpy as np
import time
N=10000000
v=np.arange(N)
Nelemes_per_group=10
Ngroups=N/Nelemes_per_group
s=np.arange(Ngroups)
g=np.repeat(s,Nelemes_per_group)
start1=time.time()
r=np.maximum.reduceat(v, np.unique(g, return_index=True)[1])
end1=time.time()
print('END first method, T=',(end1-start1),'s')
start3=time.time()
np.array(list(map(np.max,np.split(v,np.where(np.diff(g)!=0)[0]+1))))
end3=time.time()
print('END second method, (map returns an iterable) T=',(end3-start3),'s')
Run Code Online (Sandbox Code Playgroud)
结果我得到:
END first method, T= 1.6057236194610596 s
END second method, (map returns an iterable) T= 8.346540689468384 s
Run Code Online (Sandbox Code Playgroud)
有趣的是,该map方法的大部分减速都是由于list()呼叫造成的.如果我不尝试将我的map结果重新转换为list(但我必须,因为python3.x返回一个迭代器:https: //docs.python.org/3/library/functions.html#map)
您可以使用np.maximum.reduceat:
>>> _, idx = np.unique(g, return_index=True)
>>> np.maximum.reduceat(v, idx)
array([ 4, 74, 10])
Run Code Online (Sandbox Code Playgroud)
reduceat可以在此处找到有关 ufunc方法工作原理的更多信息。
性能备注
np.maximum.reduceat非常快。生成索引idx是这里花费的大部分时间。
虽然_, idx = np.unique(g, return_index=True)是一种获取索引的优雅方式,但它并不是特别快。
原因是np.unique需要先对数组进行排序,复杂度为O(n log n)。对于大型数组,这比使用多个 O(n) 操作来生成idx.
因此,对于大型数组,使用以下代码要快得多:
idx = np.concatenate([[0], 1+np.diff(g).nonzero()[0]])
np.maximum.reduceat(v, idx)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1088 次 |
| 最近记录: |