Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用列表中的随机元素创建numpy数组_Python_Arrays_List_Random_Numpy - Fatal编程技术网

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

Python 使用列表中的随机元素创建numpy数组,python,arrays,list,random,numpy,Python,Arrays,List,Random,Numpy,是否有一种有效的方法来创建任意长numpy数组,其中每个维度由从长度>=n的列表中提取的n个元素组成?对于每个维度,列表中的每个元素只能绘制一次 例如,如果我有列表l=['cat',mescaline','popcorn'],我希望能够,例如,通过键入np.random.pick_random(l,(3,2),replace=false),创建一个数组数组(['cat','popcorn'],['cat','popcorn'],['mescaline','cat']]) 谢谢。这里有一种方法可以

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

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


谢谢。

这里有一种方法可以使用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')

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

  • pythons拥有的
    random.sample
    ,简单且内置,尽管它可能不是最快的
  • numpy.random.permutation
    同样简单,但它创建了一个我们必须切片的副本,哎哟
  • numpy.random.shuffle
    速度更快,因为它可以在适当的位置进行洗牌,但我们仍然需要切片
  • numpy.random.sample
    是最快的,但它只在0到1的时间间隔内工作,所以我们有 为了规范化它,并将其转换为整数以获得随机索引,最后我们 仍然需要切片,注意规格化到我们想要的大小并不会产生均匀的随机分布
以下是一些基准

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
拥有自己的
sample,所以它看起来像是
numpy.random.shuffle
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/。。。等等,只对当前集合起作用,不知道总体,这可能是可以接受的,也可能是不可以接受的,这取决于您试图实现什么,如果您想要一组唯一的排列,那么您将生成该集合并对其进行子采样。

简单而明显的导入随机是否有问题;random.shuffle()?我想知道为什么它必须是
numpy
?通常,numpy用于数值类型的计算,因此它的名称是数值python的缩写,尽管它确实支持其他类型。。。pythons拥有
random.sample
可能更适合这个
[random.sample(['cat','mescaline','popcorn'],xrange中索引的成员数(数组数)]
..@samy vilar原因是我想避免慢循环。我将使用它进行蒙特卡罗模拟,因此我需要相当大的阵列。@jim dennis我创建大型阵列时的性能差异。谢谢你。然而,有一个细节我忘了提。新数组不应包含多次包含同一元素的维度(如果该元素在列表中未多次列出)。更新会给出所需的结果,但效率不高。而效率正是我所要求的。如果我不清楚,很抱歉。@Aae那么您应该指定哪种类型的效率对您很重要。速度记忆?速度很重要。我在上面的评论中提到了这一点(“避免慢循环”),但我想我可以说得更清楚。谢谢。但正如我在这里对另一个人说的:有一个细节我忘了提。新数组不应包含多次包含同一元素的维度(如果它在列表中未多次列出)。感谢您的努力。numpy.shuffle方法的效率还可以。但是,在阵列上进行计算时,它并不能使我避免慢循环。例如,我想做sum(随机数组,axis=1)。对不起,我不清楚我要找的是什么。umm random_array.sum(axis=1)?随机数组应为numpy类型。还请注意,根据您需要的随机数组的数量,随机洗牌可能会生成非唯一排列,如果您确实想要唯一排列,则必须手动生成并对其进行子采样,还请注意,
numpy.random.choice
是在1.7 Im中添加的,当前为1.6.1,我不确定它的性能是否需要测试,但它可能会慢一些,因为它生成了新的数组……也许我误解了,但我这样做的方式会生成一个“列表”:排列不应该是唯一的。@Aae我已经更新以使用numpy,sum也只能应用于数值,这里有字符串值,如果你想使用索引,只需将值替换为
范围(leng(values))
即可。
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]