2012-09-05 71 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