2012-09-05 107 views
4

我有一個2D numpy數組,其中包含大約12列和1000多行,每個單元格包含一個從1到5的數字。我根據我的點系統搜索最佳的六列數據1和2生成-1點,4和5生成+1。因爲3 * 1 + 1 *( - 1),所以如果某個六元組中的行包含[1,4,5,3,4,3],則該行的點應該是+2,因爲3 * 1 + 1 * = 2。下一行可以是[1,2,2,3,3,3]並且應該是-3點。首先,我嘗試了一個海峽前向循環解決方案,但是我意識到有665 280個可能的列組合需要進行比較,並且當我還需要搜索最佳的五元組,四元組等等時,這個循環將持續進行。在numpy數組中比較多列

有沒有可能是一個更聰明的numpy方式來解決我的問題?

+2

你可以發佈你的循環解決方案嗎?有時候更容易優化已經運行的代碼,而不是試圖重新發明輪子...... – mgilson

+0

發佈您的解決方案的另一個優點是它解決了含糊之處。例如,我不確定是否想要找到列出每列最多的六列(這很容易)或其他內容。 – DSM

+0

它也可能有助於更多地瞭解您的數據集。例如,聽起來你願意接受來自一行的任何六個答案 - 如果每一行都是一個觀察,爲什麼其餘的被拒絕?您的數據數組可以通過某種方式進行重構來簡化搜索空間嗎? – abought

回答

1
import numpy as np 
import itertools 

N_rows = 10 
arr = np.random.random_integers(5, size=(N_rows,12)) 
x = np.array([0,-1,-1,0,1,1]) 
y = x[arr] 

print(y) 

score, best_sextuple = max((y[:,cols].sum(), cols) 
          for cols in itertools.combinations(range(12),6)) 
print('''\ 
score: {s} 
sextuple: {c} 
'''.format(s = score, c = best_sextuple)) 

產率,例如,

score: 6 
sextuple: (0, 1, 5, 8, 10, 11) 

說明

首先,讓我們生成一個隨機例如,具有12列和10行:

N_rows = 10 
arr = np.random.random_integers(5, size=(N_rows,12)) 

現在我們可以使用numpy的索引將數字轉換在arr 1,2,...,5的值1,0,1(根據您的評分系統):

x = np.array([0,-1,-1,0,1,1]) 
y = x[arr] 

接下來,讓我們使用itertools.combinations以產生6列的所有可能的組合:

for cols in itertools.combinations(range(12),6) 

y[:,cols].sum() 

然後給出分數cols,列的選擇(一個或多個extuple)。

最後,使用max摘掉了六倍最好的成績:

score, best_sextuple = max((y[:,cols].sum(), cols) 
          for cols in itertools.combinations(range(12),6)) 
0

擴展上unutbu的再回應以上,有可能自動生成分數屏蔽數組。由於每次通過循環的值都是一致的,因此每個值的分數只需計算一次。在應用分數之前和之後,在示例6x10陣列上執行此操作的方式稍顯不雅。

>>> import numpy 
>>> values = numpy.random.randint(6, size=(6,10)) 
>>> values 
array([[4, 5, 1, 2, 1, 4, 0, 1, 0, 4], 
     [2, 5, 2, 2, 3, 1, 3, 5, 3, 1], 
     [3, 3, 5, 4, 2, 1, 4, 0, 0, 1], 
     [2, 4, 0, 0, 4, 1, 4, 0, 1, 0], 
     [0, 4, 1, 2, 0, 3, 3, 5, 0, 1], 
     [2, 3, 3, 4, 0, 1, 1, 1, 3, 2]]) 
>>> b = values.copy() 
>>> b[ b<3 ] = -1 

>>> b[ b==3 ] = 0 
>>> b[ b>3 ] = 1 
>>> b 
array([[ 1, 1, -1, -1, -1, 1, -1, -1, -1, 1], 
     [-1, 1, -1, -1, 0, -1, 0, 1, 0, -1], 
     [ 0, 0, 1, 1, -1, -1, 1, -1, -1, -1], 
     [-1, 1, -1, -1, 1, -1, 1, -1, -1, -1], 
     [-1, 1, -1, -1, -1, 0, 0, 1, -1, -1], 
     [-1, 0, 0, 1, -1, -1, -1, -1, 0, -1]]) 

順便說一句,this線程聲稱,直接在numpy的創建組合將產生比itertools 5倍左右更快的性能,雖然也許在一些可讀性爲代價的。

1
import numpy 

A = numpy.random.randint(1, 6, size=(1000, 12)) 
points = -1*(A == 1) + -1*(A == 2) + 1*(A == 4) + 1*(A == 5) 
columnsums = numpy.sum(points, 0) 

def best6(row): 
    return numpy.argsort(row)[-6:] 

bestcolumns = best6(columnsums) 
allbestcolumns = map(best6, points) 

bestcolumns現在將包含升序最好的6列。通過類似的邏輯,allbestcolumns將包含每行中最佳的六列。

+0

這就是我最初解釋這個問題的方式,但其他人給出了同樣合理的解讀。不過,我會使用'.argsort()[ - 6:]'。 – DSM

+0

關於argsort的好處。 – chthonicdaemon

+0

我已將它更改爲'argsort',但我在這裏有點新,所以我不確定在我的答案中包含這樣的建議的禮儀。這個評論用作披露。 – chthonicdaemon