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没有排序,实际上我要发布相同的..(我更喜欢使用命名参数来表示它在imoside='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