cython在矩阵中搜索值

时间:2015-06-05 18:06:34

标签: matrix cython

import numpy as np
cimport numpy as np

x = np.array(
[[1,1,0.293729457],
[1,2,0.414213648],
[1,3,0.420339974],
[2,1,0.394448377],
[2,2,0.550755237],
[2,3,0.876993966]
]
)

我有一个6x3矩阵。第1列和第2列是索引,第3列是值。 问题是如何快速查找第1列和第2列的值?例如,如果col 1 = 1且col 2 = 3,我想要返回0.420339974。

我尝试循环查找每列,但如果我有很多行,它会很慢。

3 个答案:

答案 0 :(得分:1)

杰森,

简短回答

您可以按如下方式使用np.wherenp.logical_and,如下所示:

In [10]: x[np.where(np.logical_and(x[:,0]==1,x[:,1]==3))][0][2]
Out[10]: 0.42033997400000001

答案很长

稍微解释一下,x[:,0]==1x[:,1]==3返回布尔数组,大小等于x的长度。首先,让我们定义两个变量来存储您的条件:

In [12]: a = x[:,0]==1
In [13]: b = x[:,1]==3

你不能使用Python的内置and,因为它会首先尝试将其参数转换为布尔值:

a and b

相反,使用numpy的In [15]: a and b --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-15-cb10dcaa1a1e> in <module>() ----> 1 a and b ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() 返回一个元素方式的数组。然后,numpy logical_and函数返回其参数为true的索引。从技术上讲,where的输出是一个元组,其第一个元素是一个索引数组,其中where的计算结果为真:

logical_and
使用单个数组作为参数调用的

In [16]: np.logical_and(a,b) Out[16]: array([False, False, True, False, False, False], dtype=bool) In [17]: np.where(np.logical_and(a,b)) Out[17]: (array([2]),) 等同于numpy的where

nonzero

最后,看起来您的数据可以更逻辑地组织(并且更紧凑,就此而言)仅作为值的二维矩阵:

In [18]: np.nonzero(np.logical_and(a,b))
Out[18]: (array([2]),)

然后你的查找是微不足道的,尽管从基于1的索引切换到基于0的索引:

In [25]: M = 2
In [26]: N = 3
In [27]: data = np.zeros((M,N))
In [28]: for datum in x:
data[datum[0]-1,datum[1]-1]=datum[2]

In [30]: data
Out[30]: 
array([[ 0.29372946,  0.41421365,  0.42033997],
       [ 0.39444838,  0.55075524,  0.87699397]])

-Ravi

答案 1 :(得分:1)

在我深入了解libcpp之后,我使用了以下

from libcpp.map cimport map

import numpy as np
cimport numpy as np

x = np.array(
[[1,1,0.293729457],
[1,2,0.414213648],
[1,3,0.420339974],
[2,1,0.394448377],
[2,2,0.550755237],
[2,3,0.876993966]
]
)


def F(int c1, int c2, x = x):
    cdef map[int, map[int, float]] my_map
    cdef int i
    for i in xrange(x.shape[0]):
        my_map[x[i,0]][x[i,1]] = x[i,2]

    return my_map[c1][c2]

print F(1,2)

它的工作方式类似于你的2d矩阵查找。

答案 2 :(得分:0)

这实际上取决于您的用例以及数据集的大小。如果您只需要查询一次数据集,我担心,您最终无法避免遍历所有行。

但是,如果您可以承担一些计算开销来预处理数据集以快速执行多个后续查询,那么我们会想到几种方法。

  • 最简单的可能是简单地将数据复制到2D数组,其中索引(i, j)直接对应于具有这些索引的原始数组中的行。如果您的原始数据已经排序且是同质的,那么甚至可以使用简单的ndarray.reshape来完成。
  • 了解更多fancy and general apporaches,您可以了解PyTables如何对大型数据集进行高效查询。一般而言,您可以创建必要列的索引,以便更有效地执行查询,就像使用关系数据库一样。

有许多事情可以尝试。首先,你需要决定要使用的算法,然后才能看看Cython是否值得用来优化它。