numpy.random.choice

时间:2016-07-14 13:16:08

标签: python performance numpy

我更新了代码和时间。

我试图提高代码中函数的性能。我必须生成一个包含随机元素的列表。但是,列表的不同部分必须填充来自不同集合的元素。代码示例如下。我必须一次创建数百万个这样的列表。

函数foo1是最快的,但它不能满足我的需要。它有性能参考。函数foo2和foo3做我需要的,但花费的时间几乎是foo1的处理时间的三倍。

Python 2.7.9(默认,2015年2月10日,03:29:19)。 [dclwin上的[GCC 4.2.1兼容的Apple LLVM 6.0(clang-600.0.56)]。 numpy的。的版本 ' 1.8.1'

import numpy

import timeit

_ops_1 = ["-123.456", "3.1416", "1", "2"]
_ops_2 = ["ABC", "XYZ", 'A', 'B', 'C']

size = 10

def foo1 (): 
    return numpy.random.choice(_ops_1 + _ops_2, 5*size)

def foo2 (): 
    return list(numpy.concatenate((numpy.random.choice(_ops_1, 2*size), 
        numpy.random.choice(_ops_1 + _ops_2, size),
        numpy.random.choice(_ops_2, 2*size)), 0))

def foo3 (): 
    return numpy.random.choice(_ops_1, 2*size).tolist() + \
        numpy.random.choice(_ops_1 + _ops_2, size).tolist() + \
        numpy.random.choice(_ops_2, 2*size).tolist()

### Suggested by Divakar
def random_choice_replace_True(arr,size):
    return numpy.take(arr,numpy.random.randint(0,len(arr),size))

def foo4 (): 
    return random_choice_replace_True(_ops_1, 2*size).tolist() + \
        random_choice_replace_True(_ops_1 + _ops_2, size).tolist() + \
        random_choice_replace_True(_ops_2, 2*size).tolist()

### 2nd suggestion by Divakar
def random_choice_replace_True_idx(arr,size):
    return numpy.array(arr)[numpy.random.randint(0,len(arr),size)]

def foo5 (): 
    return random_choice_replace_True_idx(_ops_1, 2*size).tolist() + \
        random_choice_replace_True_idx(_ops_1 + _ops_2, size).tolist() + \
        random_choice_replace_True_idx(_ops_2, 2*size).tolist()

###########

setup = '''import numpy

_ops_1 = ["-123.456", "3.1416", "1", "2"]
_ops_2 = ["ABC", "XYZ", 'A', 'B', 'C']

size = 10'''

# As required, Number was increased to 10 million to get closer to actual timings
timeit.timeit(foo1, setup=setup, number=10000000)

timeit.timeit(foo2, setup=setup, number=10000000)

timeit.timeit(foo3, setup=setup, number=10000000)

timeit.timeit(foo4, setup=setup, number=10000000)

timeit.timeit(foo5, setup=setup, number=10000000)

我机器上的运行时间是:

  

timeit.timeit(foo1,setup = setup,number = 10000000)   235.22050380706787

     

timeit.timeit(foo2,setup = setup,number = 10000000)   760.1884841918945

     

timeit.timeit(foo3,setup = setup,number = 10000000)   560.77258586883545

     

timeit.timeit(foo4,setup = setup,number = 10000000)   388.69550228118896

     

timeit.timeit(foo5,setup = setup,number = 10000000)   252.32089233398438

好吧,现在我将采取Divakar提出的第二个建议,这是非常好的。但欢迎其他建议!

1 个答案:

答案 0 :(得分:2)

np.random.choice的可选参数replace设置为True会返回输入数组中随机选择的元素,并且可以重复这些元素。我们可以通过创建覆盖数组长度的随机索引并索引到数组中进行选择来模拟这种行为。因此,我们可以用这样的东西模拟内置 -

def random_choice_replace_True(A,size):
    return np.array(A)[np.random.randint(0,len(A),size)]

如果您正在处理已经是NumPy数组的输入,则可以跳过np.array(A)部分进行转换,只需在那里使用A