【问题标题】:Permute list of lists with mixed elements (np.random.permutation() fails with ValueError)置换具有混合元素的列表列表(np.random.permutation() 失败并出现 ValueError)
【发布时间】:2017-01-16 20:31:21
【问题描述】:

我正在尝试置换由具有混合类型元素的子列表组成的列表:

import numpy as np

a0 = ['122', 877.503017, 955.471176, [21.701201, 1.315585]]
a1 = ['176', 1134.076908, 1125.504758, [19.436181, 0.9987899]]
a2 = ['177', 1038.686843, 1018.987868, [19.539959, 1.183997]]
a3 = ['178', 878.999081, 1022.050447, [19.6448771, 1.1867719]]

a = [a0, a1, a2, a3]

b = np.random.permutation(a)

这将失败:

ValueError: cannot set an array element with a sequence

是否有内置函数可以让我生成这样的排列?

我需要生成一个随机排列,我并不是要获得所有可能的排列。


我检查了三个答案:

import time
import random

# np.random.permutation()
start = time.time()
for _ in np.arange(100000):
    b = np.random.permutation([np.array(i, dtype='object') for i in a])
print(time.time() - start)

# np.random.shuffle()
start = time.time()
for _ in np.arange(100000):
    b = a[:]
    np.random.shuffle(b)
print(time.time() - start)

# random.shuffle()
start = time.time()
for _ in np.arange(100000):
    random.shuffle(a)
print(time.time() - start)

结果是:

1.47580695152
0.11471414566
0.26300907135

所以np.random.shuffle() 解决方案比np.random.permutation() 快大约10 倍,比random.shuffle() 快2 倍。

【问题讨论】:

  • 您是尝试生成列表的随机排列,还是获取所有排列?
  • 只是一个随机排列。我会将此信息添加到问题中。
  • 这是一种非常奇怪的 NumPy 使用方式。如果您想尝试使用 NumPy 构建这样的数据结构,您将不得不处理很多尴尬和低效率的问题。
  • 很可能就是这样。或许使用下面建议的random 包会更有效。

标签: python numpy permutation


【解决方案1】:

使用np.random.shuffle怎么样?

# if you want the result in another list, otherwise just apply shuffle to a
b = a[:]
# shuffle the elements
np.random.shuffle(b)
# see the result of the shuffling
print(b)

请参阅this answer 了解shuffle 和permutation 之间的区别

【讨论】:

  • 这在我的情况下返回None? o_O
  • @Gabriel shuffle 就地打乱数组。打印b 以查看结果。
  • 当然。这看起来比 Kasramvd 的答案还要简单。也许我需要做一些时间测试,看看哪个更有效。
  • 正如链接问题中突出显示的那样,permutation 实际上使用 shuffle,正如您从source code 中看到的那样,因此您可能会发现shuffle 更多高效(或更可能,差异可以忽略不计)
【解决方案2】:

如果您只想创建a = [a0, a1, a2, a3] 的随机排列,我是否建议改为排列索引?

>>> random_indices = np.random.permutation(np.arange(len(a)))
>>> a_perm = [a[i] for i in random_indices]
... # Or just use the indices as you see fit...

如果您为此使用 numpy just,请完全跳过 numpy,而只需使用 random.shuffle 即可:

>>> import random
>>> random.shuffle(a)

【讨论】:

    【解决方案3】:

    您需要将列表转换为类型为object() 的numpy 数组,以便random.permutation() 可以将列表解释为numpy 类型而不是序列:

    >>> a = [np.array(i, dtype='object') for i in a]
    >>> 
    >>> np.random.permutation(a)
    array([['122', 877.503017, 955.471176, [21.701201, 1.315585]],
           ['177', 1038.686843, 1018.987868, [19.539959, 1.183997]],
           ['178', 878.999081, 1022.050447, [19.6448771, 1.1867719]],
           ['176', 1134.076908, 1125.504758, [19.436181, 0.9987899]]], dtype=object)
    

    您还可以使用 numpy.array() 从列表中创建一个 uniqe 数组,而不是使用列表推导:

    >>> a = np.array((a0, a1, a2, a3), dtype='object')
    >>> a
    array([['122', 877.503017, 955.471176, [21.701201, 1.315585]],
           ['176', 1134.076908, 1125.504758, [19.436181, 0.9987899]],
           ['177', 1038.686843, 1018.987868, [19.539959, 1.183997]],
           ['178', 878.999081, 1022.050447, [19.6448771, 1.1867719]]], dtype=object)
    >>> np.random.permutation(a)
    array([['122', 877.503017, 955.471176, [21.701201, 1.315585]],
           ['177', 1038.686843, 1018.987868, [19.539959, 1.183997]],
           ['176', 1134.076908, 1125.504758, [19.436181, 0.9987899]],
           ['178', 878.999081, 1022.050447, [19.6448771, 1.1867719]]], dtype=object)
    >>> np.random.permutation(a)
    array([['177', 1038.686843, 1018.987868, [19.539959, 1.183997]],
           ['176', 1134.076908, 1125.504758, [19.436181, 0.9987899]],
           ['178', 878.999081, 1022.050447, [19.6448771, 1.1867719]],
           ['122', 877.503017, 955.471176, [21.701201, 1.315585]]], dtype=object)
    

    【讨论】:

      【解决方案4】:

      random.shuffle() 更改列表。

      就地改变结构的 Python API 方法通常返回 None。

      请尝试random.sample(a,len(a))

      代码如下:

      a = a[:]
      b = random.sample(a,len(a))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-08-31
        • 1970-01-01
        • 2012-09-21
        • 2013-11-17
        • 1970-01-01
        • 2017-04-07
        • 1970-01-01
        • 2019-04-28
        相关资源
        最近更新 更多