2015-07-10 99 views
2

我有一个程序需要一些大的NumPy数组,并且基于某些外部数据,通过向随机选择的单元格中添加一个来增加它们,直到数组的总和等于外部数据为止。简化和更小的版本是这样的:在NumPy数组中随机增长值

import numpy as np 
my_array = np.random.random_integers(0, 100, [100, 100]) 
## Just creating a sample version of the array, then getting it's sum: 
np.sum(my_array) 
499097 

所以,假如我想,直到其总和为100万增长了阵列,而且我想通过不断地随机细胞,加入1至,直到我们这样做打的总和,我做的是这样的:

diff = 1000000 - np.sum(my_array) 
counter = 0 
while counter < diff: 
    row = random.randrange(0,99) 
    col = random.randrange(0,99) 
    coordinate = [row, col] 
    my_array[coord] += 1 
    counter += 1 

当行/列结合起来,返回数组中随机单元格,然后该单元由1土生土长的IT重复,直到次数由它将1加入随机单元格==原始数组的总和与目标总和(1,000,000)之间的差值。

但是,当我运行此检查后的结果 - 总是总是关闭。在与上述相同的号码运行它后,这种情况下:

np.sum(my_array) 
99667203 

我无法弄清楚什么是占这个巨大的差异。是否有更多pythonic的方式去做这件事?

回答

0

my_array[coord]替换为my_array[row][col]。您的方法选择了两个随机整数,并将1添加到对应于这两个整数的行中的每个条目。

基本上你对numpy索引数组有些小误解。

编辑:为了更清楚。 发布的代码选择了两个数字,比如30和45,并添加1〜30行的所有100个条目和行45

的所有100个条目从这个你所期望的总和是100,679,697 = 200*(1,000,000 - 499,097) + 499,097

然而,当随机整数是相同的(比如45和45)时,第45列中的每个入口只增加1个,而不是2,因此在这种情况下,总和仅跳过100.

+2

这应该是'my_array [row,col]'。 'my_array [row] [col]'会起作用,但效率不高。 –

1

my_array[coordinate]不会做你所做的期望。它将选择多行并将1添加到所有这些条目中。您可以简单地使用my_array[row, col]

你可以简单地写类似:

for _ in range(1000000 - np.sum(my_array)): 
    my_array[random.randrange(0, 99), random.randrange(0, 99)] += 1 

(或xrange代替range如果使用Python 2.x的)

+0

@WarrenWeckesser:谢谢,纠正。我实际上是在我的例子中编写的,但由于某种原因,并没有在第一个例子中。 – grovesNL

0

与原有方法的问题是,你有你的索引数组列表,它被解释为行维度中的一系列索引,而不是作为行/列维度中的单独索引(see here)。 尝试通过代替列表的元组:

coord = row, col 
my_array[coord] += 1 

快得多的方法是找到的总和超过所述输入阵列和所述目标值之间的差,然后生成包含相同编号的数组的随机索引到阵列和递增它们全部在一个去,这样就避免了在Python循环:

import numpy as np 

def grow_to_target(A, target=1000000, inplace=False): 

    if not inplace: 
     A = A.copy() 

    # how many times do we need to increment A? 
    n = target - A.sum() 

    # pick n random indices into the flattened array 
    idx = np.random.random_integers(0, A.size - 1, n) 

    # how many times did we sample each unique index? 
    uidx, counts = np.unique(idx, return_counts=True) 

    # increment the array counts times at each unique index 
    A.flat[uidx] += counts 

    return A 

例如:

a = np.zeros((100, 100), dtype=np.int) 

b = grow_to_target(a) 
print(b.sum()) 
# 1000000 

%timeit grow_to_target(a) 
# 10 loops, best of 3: 91.5 ms per loop