7

我不确定这是否可能,但这里有。假设我有一个数组:

array1 = [0,.1,.2,.3,.4,.5,.6,.7,.8,.9,1]

现在我想创建一个由 5 个元素组成的 numpy 1D 数组,这些元素从 array1 中随机抽取并且条件是总和等于 1。示例类似于一个 numpy 数组,看起来像[.2,.2,.2,.1,.1].

  • 目前我使用随机模块和如下所示的选择功能: range1= np.array([choice(array1),choice(array1),choice(array1),choice(array1),choice(array1)]) 然后检查 range1 以查看它是否符合条件;我想知道是否有更快的方法,类似于 randomArray = np.random.random()代替。

  • 如果我可以将这个数组存储在某个库中会更好,这样如果我尝试生成 100 个这样的数组,就不会重复,但这不是必需的。

4

3 回答 3

7

numpy.random.choice如果您使用 numpy 1.7.0+,则可以使用:

>>> import numpy as np
>>> array1 = np.array([0,.1,.2,.3,.4,.5,.6,.7,.8,.9,1])
>>> np.random.choice(array1, 5)
array([ 0. ,  0. ,  0.3,  1. ,  0.3])
>>> np.random.choice(array1, 5, replace=False)
array([ 0.6,  0.8,  0.1,  0. ,  0.4])

要获得总和等于1的5个元素,

  • 生成 4 个随机数。
  • 从 1 -> x 中减去 4 个数字的总和
  • 如果 x 包含在 array1 中,则将其用作最终数字;或重复

>>> import numpy as np
>>> 
>>> def solve(arr, total, n):
...     while True:
...         xs = np.random.choice(arr, n-1)
...         remain = total - xs.sum()
...         if remain in arr:
...             return np.append(xs, remain)
... 
>>> array1 = np.array([0,.1,.2,.3,.4,.5,.6,.7,.8,.9,1])
>>> print solve(array1, 1, 5)
[ 0.1  0.3  0.4  0.2  0. ]

另一个版本(假设给定数组已排序):

EPS = 0.0000001
def solve(arr, total, n):
    while True:
        xs = np.random.choice(arr, n-1)
        t = xs.sum()
        i = arr.searchsorted(total - t)
        if abs(t + arr[i] - total) < EPS:
            return np.append(xs, arr[i])
于 2013-09-09T04:12:09.023 回答
2

不久前我不得不做类似的事情。

def getRandomList(n, source):
    '''
    Returns a list of n elements randomly selected from source.
    Selection is done without replacement.

    '''

    list = source
    indices = range(len(source))
    randIndices = []
    for i in range(n):
        randIndex = indices.pop(np.random.randint(0, high=len(indices)))
        randIndices += [randIndex]

    return [source[index] for index in randIndices]


data = [1,2,3,4,5,6,7,8,9]
randomData = getRandomList(4, data)
print randomData
于 2013-09-09T04:08:05.550 回答
2

如果您不关心输出序列中值的顺序,则列表中加起来为 1 的值的 5 值组合的数量非常少。但是,在您提出的特定情况下,计算起来有点复杂,因为浮点值存在舍入问题。如果您使用一组整数(例如range(11))并找到加起来为 10 的组合,则可以更轻松地解决该问题。然后,如果您需要小数值,只需将结果中的值除以 10。

无论如何,这是一个生成器,它产生所有可能的集合,这些集合加起来为给定值:

def picks(values, n, target):
    if n == 1:
        if target in values:
            yield (target,)
        return
    for i, v in enumerate(values):
        if v <= target:
            for r in picks(values[i:], n-1, target-v):
                yield (v,)+r

以下是数字 0 到 10 的结果:

>>> for r in picks(range(11), 5, 10):
    print(r)

(0, 0, 0, 0, 10)
(0, 0, 0, 1, 9)
(0, 0, 0, 2, 8)
(0, 0, 0, 3, 7)
(0, 0, 0, 4, 6)
(0, 0, 0, 5, 5)
(0, 0, 1, 1, 8)
(0, 0, 1, 2, 7)
(0, 0, 1, 3, 6)
(0, 0, 1, 4, 5)
(0, 0, 2, 2, 6)
(0, 0, 2, 3, 5)
(0, 0, 2, 4, 4)
(0, 0, 3, 3, 4)
(0, 1, 1, 1, 7)
(0, 1, 1, 2, 6)
(0, 1, 1, 3, 5)
(0, 1, 1, 4, 4)
(0, 1, 2, 2, 5)
(0, 1, 2, 3, 4)
(0, 1, 3, 3, 3)
(0, 2, 2, 2, 4)
(0, 2, 2, 3, 3)
(1, 1, 1, 1, 6)
(1, 1, 1, 2, 5)
(1, 1, 1, 3, 4)
(1, 1, 2, 2, 4)
(1, 1, 2, 3, 3)
(1, 2, 2, 2, 3)
(2, 2, 2, 2, 2)

您可以随机选择其中一个(使用random.choice),或者如果您打算使用其中的许多并且不想重复自己,则可以使用random.shuffle,然后进行迭代。

results = list(picks(range(11), 5, 10))
random.shuffle(results)

for r in results:
    # do whatever you want with r
于 2013-09-09T04:48:21.900 回答