2015-02-11 246 views
0

我有一個索引數組(可能重複),其中我在另一個二維矩陣中的每個這些索引增加1.有幾個建議,並且這個answer建議使用np.ravel_multi_indexnumpy:ravel_multi_index遞增循環索引循環不同的結果循環

所以,我試了一下,但他們似乎並沒有給我同樣的答案。任何想法爲什麼?

raveled = np.ravel_multi_index(legit_indices.T, acc.shape) 
counts = np.bincount(raveled) 
acc = np.resize(counts, acc.shape) 

acc2 = np.zeros(acc2.shape) 
for i in legit_indices: 
    acc2[i[0], i[1]] += 1 

(Pdb) np.array_equal(acc, acc2) 
False 

(Pdb) acc[493][5] 
135 
(Pdb) acc2[493][5] 
0.0 

回答

1

您當前的方法存在一些問題。首先,np.bincount(x) 會給你計數x正整數值從0開始max(x)結束:

print(np.bincount([1, 1, 3, 3, 3, 4])) 
# [0, 2, 0, 3, 1] 
# i.e. [count for 0, count for 1, count for 2, count for 3, count for 4] 

因此,如果不是在acc.flat每個位置被索引,長度 np.bincount(raveled)將大於唯一索引的數量。什麼 你實際上想要的是計數只有acc.flat那些 索引至少一次。

其次,你想要做的是將bin計數分配到相應的 指數到acc.flat。您撥打np.resize所要做的就是重複您的二進制數組中的部分 ,以使其與acc.flat, 相同,然後將其重新塑造成與acc相同的形狀。這不會導致將 計數器分配到acc中的正確位置!

我會解決這個問題的方法是使用np.unique代替 np.bincount,並用它來恢復這兩個獨特的指數及其對應的 計數。然後這些可用於將正確的計數分配到acc內的正確唯一位置:

import numpy as np 

# some example data 
acc = np.zeros((4, 3)) 
legit_indices = np.array([[0, 1], 
          [0, 1], 
          [1, 2], 
          [1, 0], 
          [1, 0], 
          [1, 0]]) 

# convert the index array into a set of indices into acc.flat 
flat_idx = np.ravel_multi_index(legit_indices.T, acc.shape) 

# get the set of unique indices and their corresponding counts 
uidx, ucounts = np.unique(flat_idx, return_counts=True) 

# assign the count value to each unique index in acc.flat 
acc.flat[uidx] = ucounts 

# confirm that this matches the result of your for loop 
acc2 = np.zeros_like(acc) 
for ii, jj in legit_indices: 
    acc2[ii, jj] += 1 

assert np.array_equal(acc, acc2) 
+0

我理解了關於使用np.unique的第二部分。但我不太確定,我得到的關於np.bincount的部分是np.bincount(raveled)的長度將大於唯一索引的數目。 「你介意詳細說明還是陳述一個例子? – goh 2015-02-11 14:30:59

+0

我舉了一個例子:'np.bincount([1,3,3,3,4])'給你指數爲0,1,2,3和4,而你只希望實際發生的指數至少有一次(即1,3和4)。 – 2015-02-11 14:42:43