Python 使用列表中的随机元素创建numpy数组
是否有一种有效的方法来创建任意长numpy数组,其中每个维度由从长度>=n的列表中提取的n个元素组成?对于每个维度,列表中的每个元素只能绘制一次 例如,如果我有列表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']]) 谢谢。这里有一种方法可以
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
是最快的,但它只在0到1的时间间隔内工作,所以我们有 为了规范化它,并将其转换为整数以获得随机索引,最后我们 仍然需要切片,注意规格化到我们想要的大小并不会产生均匀的随机分布numpy.random.sample
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]