Python numpy.searchsorted包含多个源

Python numpy.searchsorted包含多个源,python,numpy,Python,Numpy,假设我有两个数组 a = [0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 6] b = [1, 2, 1, 2, 1, 4, 7, 9, 4, 8, 1, 1] 如您所见,当将a和b视为超级数组的列时,上述数组将被排序 现在,我想对这个数组进行搜索排序。例如,如果我搜索(3,7)(a=3和b=7),我应该得到6 每当a中存在重复值时,应继续搜索b中的值 有内置的numpy方法吗?或者,假设我的数组中有一百万个条目,那么什么是最有效的方法呢 我尝试使用numpy.recarr

假设我有两个数组

a = [0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 6]
b = [1, 2, 1, 2, 1, 4, 7, 9, 4, 8, 1, 1]
如您所见,当将
a
b
视为超级数组的列时,上述数组将被排序

现在,我想对这个数组进行搜索排序。例如,如果我搜索(3,7)(a=3和b=7),我应该得到6

每当
a
中存在重复值时,应继续搜索
b
中的值

有内置的numpy方法吗?或者,假设我的数组中有一百万个条目,那么什么是最有效的方法呢

我尝试使用numpy.recarray,创建一个带有
a
b
的recarray,并尝试在其中搜索,但出现以下错误

TypeError: expected a readable buffer object

非常感谢您的帮助。

您可以使用重复的
搜索从左到右排序:

left, right = np.searchsorted(a, 3, side='left'), np.searchsorted(a, 3, side='right')
index = left + np.searchsorted(b[left:right], 7)
n阵列扩展:

import numpy as np

def searchsorted_multi(*args):
    v = args[-1]
    if len(v) != len(args[:-1]):
        raise ValueError
    l, r = 0, len(args[0])
    ind = 0
    for vi, ai in zip(v, args[:-1]):
        l, r = [np.searchsorted(ai[l:r], vi, side) for side in ('left', 'right')]
        ind += l
    return ind

if __name__ == "__main__":
    a = [0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 6]
    b = [1, 2, 1, 2, 1, 4, 7, 9, 4, 8, 1, 1]
    c = [1, 2, 1, 2, 1, 4, 7, 9, 4, 8, 1, 2]

    assert(searchsorted_multi(a, b, (3, 7)) == 6)
    assert(searchsorted_multi(a, b, (3, 0)) == 5)
    assert(searchsorted_multi(a, b, c, (6, 1, 2)) == 12)

下面是一个有趣的方法(尽管它不是最有效的方法,因为我相信它是O(n)而不是O(log(n)),正如ecatmur的答案一样;但是,它更紧凑):

例如:

>>> a = np.array([0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 6])
>>> b = np.array([1, 2, 1, 2, 1, 4, 7, 9, 4, 8, 1, 1])
>>> np.searchsorted(a + 1j*b, 4 + 1j*8)
9

你快到了。这只是因为
numpy.record
(考虑到您收到的错误消息,我假设您使用的是
numpy.record)并不是您真正想要的;只需创建一个单项记录数组:

>>> a_b = numpy.rec.fromarrays((a, b))
>>> a_b
rec.array([(0, 1), (0, 2), (1, 1), (1, 2), (2, 1), (3, 4), (3, 7), (3, 9),
       (4, 4), (4, 8), (5, 1), (6, 1)], 
      dtype=[('f0', '<i8'), ('f1', '<i8')])
>>> numpy.searchsorted(a_b, numpy.array((3, 7), dtype=a_b.dtype))
6
对记录数组进行排序:

>>> a_b = numpy.rec.fromarrays((a, b))
>>> a_b[a_b.argsort()]
rec.array([(0, 1), (0, 2), (1, 1), (1, 2), (2, 1), (3, 4), (3, 7), (3, 9),
       (4, 4), (4, 8), (5, 1), (6, 1)], 
      dtype=[('f0', '<i8'), ('f1', '<i8')])
>>> a_b.sort()
>>> a_b
rec.array([(0, 1), (0, 2), (1, 1), (1, 2), (2, 1), (3, 4), (3, 7), (3, 9),
       (4, 4), (4, 8), (5, 1), (6, 1)], 
      dtype=[('f0', '<i8'), ('f1', '<i8')])
>>a_b=numpy.rec.fromarrays((a,b))
>>>a_b[a_b.argsort()]
记录数组([(0,1),(0,2),(1,1),(1,2),(2,1),(3,4),(3,7),(3,9),
(4, 4), (4, 8), (5, 1), (6, 1)], 
dtype=[('f0','或不带numpy:

>>> import bisect
>>> a = [0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 6]
>>> b = [1, 2, 1, 2, 1, 4, 7, 9, 4, 8, 1, 1]
>>> bisect.bisect_left(zip(a,b), (3,7))
6
这对我很有用:

>>> a = [0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 6]
>>> b = [1, 2, 1, 2, 1, 4, 7, 9, 4, 8, 1, 1]
>>> Z = numpy.array(zip(a, b), dtype=[('a','int'), ('b','int')])
>>> Z.searchsorted(numpy.asarray((3,7), dtype=Z.dtype))
6

我认为诀窍可能是确保searchsorted的参数具有与数组相同的数据类型。当我尝试
Z.searchsorted((3,7))
时,我得到一个segfault。

如果
b
中不存在
7
,则失败。事实上,我的答案被另一个受您启发的版本所取代:)b没有排序,实际上我要发布相同的..(我更喜欢使用命名参数来表示它在imo
side='right'
中读起来更好的那一面)非常好。但是如果我有更多的列,这个解决方案将无法扩展。我的意思是,对python解释器senderly的更多工作刚刚给出了我想要的解决方案。太好了!我错过了。谢谢!
>>> import bisect
>>> a = [0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 6]
>>> b = [1, 2, 1, 2, 1, 4, 7, 9, 4, 8, 1, 1]
>>> bisect.bisect_left(zip(a,b), (3,7))
6
>>> a = [0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 6]
>>> b = [1, 2, 1, 2, 1, 4, 7, 9, 4, 8, 1, 1]
>>> Z = numpy.array(zip(a, b), dtype=[('a','int'), ('b','int')])
>>> Z.searchsorted(numpy.asarray((3,7), dtype=Z.dtype))
6