python – 使用列表中的随机元素创建numpy数组

有没有一种有效的方法来创建一个任意长的numpy数组,其中每个维度包含从长度为> = n的列表中绘制的n个元素?列表中的每个元素只能为每个维度绘制一次.

例如,如果我有列表l = [‘cat’,’mescaline’,’popcorn’],我希望能够,例如通过键入类似np.random.pick_random(l,(3,2)的内容,replace = false),创建一个数组数组([[‘cat’,’popcorn’],[‘cat’,’popcorn’],[‘mescaline’,’cat’]]).

谢谢.

最佳答案
有几种方法可以做到这一点,每种方式都有自己的优点/缺点,以下四种方式
从我的头顶…

> pythons拥有random.sample,很简单并内置,虽然它可能不是最快的……
> numpy.random.permutation再次简单,但它创建了一个我们必须切片的副本,哎哟!
> numpy.random.shuffle更快,因为它在适当的位置改组,但我们仍然需要切片.
> numpy.random.sample是最快的,但它只适用于0到1的间隔,所以我们有
为了规范化它,并将其转换为int以获得随机索引,最后我们
仍然需要切片,注意归一化到我们想要的大小不会产生均匀的随机分布.

这是一些基准.

import timeit
from matplotlib import pyplot as plt

setup = \
"""
import numpy
import random

number_of_members = 20
values = range(50)
"""

number_of_repetitions = 20
array_sizes = (10, 200)

python_random_times = [timeit.timeit(stmt = "[random.sample(values, number_of_members) for index in xrange({0})]".format(array_size),
                                     setup = setup,                      
                                     number = number_of_repetitions)
                                        for array_size in xrange(*array_sizes)]

numpy_permutation_times = [timeit.timeit(stmt = "[numpy.random.permutation(values)[:number_of_members] for index in xrange({0})]".format(array_size),
                               setup = setup,
                               number = number_of_repetitions)
                                    for array_size in xrange(*array_sizes)]

numpy_shuffle_times = [timeit.timeit(stmt = \
                                """
                                random_arrays = []
                                for index in xrange({0}):
                                    numpy.random.shuffle(values)
                                    random_arrays.append(values[:number_of_members])
                                """.format(array_size),
                                setup = setup,
                                number = number_of_repetitions)
                                     for array_size in xrange(*array_sizes)]                                                                    

numpy_sample_times = [timeit.timeit(stmt = \
                                    """
                                    values = numpy.asarray(values)
                                    random_arrays = [values[indices][:number_of_members] 
                                                for indices in (numpy.random.sample(({0}, len(values))) * len(values)).astype(int)]
                                    """.format(array_size),
                                    setup = setup,
                                    number = number_of_repetitions)
                                         for array_size in xrange(*array_sizes)]                                                                                                                                            

line_0 = plt.plot(xrange(*array_sizes),
                             python_random_times,
                             color = 'black',
                             label = 'random.sample')

line_1 = plt.plot(xrange(*array_sizes),
         numpy_permutation_times,
         color = 'red',
         label = 'numpy.random.permutations'
         )

line_2 = plt.plot(xrange(*array_sizes),
                    numpy_shuffle_times,
                    color = 'yellow',
                    label = 'numpy.shuffle')

line_3 = plt.plot(xrange(*array_sizes),
                    numpy_sample_times,
                    color = 'green',
                    label = 'numpy.random.sample')

plt.xlabel('Number of Arrays')
plt.ylabel('Time in (s) for %i rep' % number_of_repetitions)
plt.title('Different ways to sample.')
plt.legend()

plt.show()

结果:

所以它看起来像numpy.random.permutation是最糟糕的,并不奇怪,pythons拥有random.sample持有它自己,所以它看起来像numpy.random.shuffle和numpy.random.sample与numpy.random之间的紧密竞争虽然numpy.random.sample有更高的内存占用,但我还是更喜欢它,因为我真的不需要构建数组我只需要随机索引……

$uname -a
Darwin Kernel Version 10.8.0: Tue Jun  7 16:33:36 PDT 2011; root:xnu-1504.15.3~1/RELEASE_I386 i386

$python --version
Python 2.6.1

$python -c "import numpy; print numpy.__version__"
1.6.1

UPDATE

不幸的是,numpy.random.sample不会从一个人群中绘制出独特的元素,所以你会得到复制,所以坚持使用shuffle同样快.

更新2

如果你想保持在numpy中以利用它的一些内置功能,只需将值转换为numpy数组.

import numpy as np
values = ['cat', 'popcorn', 'mescaline']
number_of_members = 2
N = 1000000
random_arrays = np.asarray([values] * N)
_ = [np.random.shuffle(array) for array in random_arrays]
subset = random_arrays[:, :number_of_members]

注意,这里的N非常大,因此你将得到重复的排列数,通过排列我的意思是在排列中没有重复值的值的顺序,因为从根本上说,如果只计算任何给定有限集的有限数量的排列如果只选择k个元素n!/(n – k),则整个集合然后是n!即使不是这种情况,意味着我们的集合要大得多,我们仍然可能依赖于随机函数实现重复,因为shuffle / permutation / …等等只适用于当前集合并且不知道对于人口,这可能是可接受的,也可能是不可接受的,取决于你想要实现的目标,如果你想要一组独特的排列,那么你将生成该集合并对其进行二次抽样.

转载注明原文:python – 使用列表中的随机元素创建numpy数组 - 代码日志