从长numpy数组中保持一个元素超过两个的最快方法?

时间:2014-10-12 13:31:11

标签: python arrays numpy

让我们考虑一个numpy数组

a = array([1,2,25,13,10,9,4,5])

包含偶数个元素。 我需要每两个随机保留一个数组元素: 第一个或第二个,然后是第三个或第四个,等等。 例如,使用a,它应该导致:

c =  array([1,13,9,5])
d = array([2,13,10,4])
e = array([2,25,10,5])

我必须在数百个元素的长数组和巨大的循环上的数千个数组上这样做。什么是使用pair_index+random.randint(0,1)迭代元素并保持或删除一对二的最快算法 每三,四等保持一个元素的通用方法会很好;-) 感谢

结果:

import timeit
import numpy

def soluce1():
    k=2
    a = numpy.array([1,2,25,13,10,9,4,5])
    aa = a.reshape(-1, k)
    i = numpy.random.randint(k, size = aa.shape[0])
    return numpy.choose(i, aa.T)
def soluce2():
    k=2
    a = numpy.array([1,2,25,13,10,9,4,5])
    w = len(a) // k
    i = numpy.random.randint(0, 2, w) + numpy.arange(0, 2 * w, 2) 
    return a[i]
def random_skip():
    a= numpy.array([1,2,25,13,10,9,4,5])
    k=2
    idx = numpy.arange(0, len(a), k)
    idx += numpy.random.randint(k, size=len(idx))
    idx = numpy.clip(idx, 0, len(a)-1)
    return a[idx]


>     ts1=timeit.timeit(stmt='soluce1()',setup='from __main__ import soluce1',number=10000)
> --> 161 µs
>     ts2=timeit.timeit(stmt='soluce2()',setup='from __main__ import soluce2',number=10000)
> --> 159 µs
>     ts3=timeit.timeit(stmt='random_skip()',setup='from __main__ import random_skip',number=10000)
> --> 166 µs

似乎是等效的提案。再次感谢所有人。

3 个答案:

答案 0 :(得分:4)

您可以使用精美索引a[idx]

选择元素
def random_skip(a, skipsize=2):
    idx = np.arange(0, len(a), skipsize)
    idx += np.random.randint(skipsize, size=len(idx))
    idx = np.clip(idx, 0, len(a)-1)
    return a[idx]    


In [141]: a = array([1,2,25,13,10,9,4,5])        
In [142]: random_skip(a)
Out[142]: array([ 1, 13,  9,  4])

In [143]: random_skip(a, skipsize=3)
Out[143]: array([1, 9, 5])

In [144]: random_skip(a, skipsize=4)
Out[144]: array([ 1, 10])

idx = np.arange(0, len(a), skipsize)选择每个组中的第一个项目。

idx += np.random.randint(skipsize, size=len(idx)) 将索引随机化为每个组中的某个项目。

如果skipsize不是idx = np.clip(idx, 0, len(a)-1)长度的倍数,

a可以防止索引超出范围。

答案 1 :(得分:3)

np.choose对于从一组数组或2dim数组中选择元素非常有用(而且速度快!)。因此,您可以将数组重新整形为Mx2,并使用np.choose切片:

a = array([1,2,25,13,10,9,4,5])
k = 2

aa = a.reshape(-1, k)  # 1dim -> 2dim
i = np.random.randint(k, size = aa.shape[0]) # random indices
np.choose(i, aa.T)
=> array([ 1, 13,  9,  4])

答案 2 :(得分:1)

一个解决方案可以是:

>>> xs
array([ 1,  2, 25, 13, 10,  9,  4,  5])
>>> k = len(xs) // 2
>>> i = np.random.randint(0, 2, k) + np.arange(0, 2 * k, 2) 
>>> xs[i]
array([ 1, 13, 10,  5]

只要数组长度是步长的倍数,就可以推广到其他步长;比如步长为4:

>>> k = len(xs) // 4
>>> i = np.random.randint(0, 4, k) + np.arange(0, 4 * k, 4)
>>> xs[i]
array([1, 5])

替代地

>>> np.apply_along_axis(np.random.choice, 1, xs.reshape(len(xs)/2, 2))
array([ 2, 13, 10,  4])
>>> np.apply_along_axis(np.random.choice, 1, xs.reshape(len(xs)/4, 4))
array([ 1, 10])