用来自lis的随机元素创建numpy数组

2024-05-16 13:22:32 发布

您现在位置:Python中文网/ 问答频道 /正文

是否有一种有效的方法来创建任意的长numpy数组,其中每个维度都由从长度列表中提取的元素组成?列表中的每个元素只能为每个维度绘制一次。

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

谢谢你。


Tags: 方法numpy元素列表键入np绘制random
3条回答

下面是一种使用numpy的方法np.random.randint

In [68]: l = np.array(['cat', 'mescaline', 'popcorn'])

In [69]: l[np.random.randint(len(l), size=(3,2))]
Out[69]: 
array([['cat', 'popcorn'],
       ['popcorn', 'popcorn'],
       ['mescaline', 'cat']], 
      dtype='|S9')

编辑:在每个元素在每行最多出现一次的附加详细信息之后

这不是很节省空间,你需要更好的吗?

In [29]: l = np.array(['cat', 'mescaline', 'popcorn'])

In [30]: array([np.random.choice(l, 3, replace=False) for i in xrange(5)])
Out[30]: 
array([['mescaline', 'popcorn', 'cat'],
       ['mescaline', 'popcorn', 'cat'],
       ['popcorn', 'mescaline', 'cat'],
       ['mescaline', 'cat', 'popcorn'],
       ['mescaline', 'cat', 'popcorn']], 
      dtype='|S9')

有几种方法可以做到这一点,每种方法都有其优缺点,下面四种方法 从我的头顶。。。

  • Python自己的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()

结果是:

enter image description here

所以看起来numpy.random.permutation是最糟糕的,这并不奇怪,Python拥有自己的random.sample是拥有自己的,所以看起来它是numpy.random.shufflenumpy.random.sample之间的一场势均力敌的竞赛,并且numpy.random.sample逐渐消失,所以两者都应该足够了,尽管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

更新

不幸的是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相当大,因此你将得到重复的置换数,通过置换,我指的是值的顺序,而不是置换内的重复值,因为从根本上讲,任何给定的有限集上都有有限的置换数,如果只是计算整个集,那么它就是N!,如果只选择k个元素,则其n!/(n-k)!即使不是这样,也就是说我们的集合要大得多,我们仍然可能根据随机函数的实现而得到重复,因为shuffle/permutation/。。。等等,只使用当前集合,不知道总体,这可能是可以接受的,也可能是不可以接受的,这取决于你试图实现什么,如果你想要一组唯一的排列,那么你将生成该集合并对其进行子采样。

>>> import numpy
>>> l = numpy.array(['cat', 'mescaline', 'popcorn'])
>>> l[numpy.random.randint(0, len(l), (3, 2))]
array([['popcorn', 'mescaline'],
       ['mescaline', 'popcorn'],
       ['cat', 'cat']], 
      dtype='|S9')

相关问题 更多 >