4

フォームに2つの配列があるとしましょう

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

ここで、この配列に対してsearchsortedを実行します。たとえば、(3、7)(a=3およびb=7)を検索すると、6が得られます。

に重複する値がある場合は常にa、検索は。の値で続行する必要がありますb

それを行うための組み込みのnumpyメソッドはありますか?または、配列に100万のエントリがあると仮定すると、これを効率的に行う方法は何でしょうか。

numpy.recarrayを使用して1つのrecarrayを作成し、それを検索しようabしましたが、次のエラーが発生します。

TypeError: expected a readable buffer object

どんな助けでも大歓迎です。

4

6 に答える 6

4

searchsorted左右から繰り返し使用できます:

left, right = np.searchsorted(a, 3, side='left'), np.searchsorted(a, 3, side='right')
index = left + np.searchsorted(b[left:right], 7)
于 2012-08-08T16:06:25.837 に答える
4

あなたはほとんどそこにいます。ただ、numpy.record(受け取ったエラー メッセージを考えると、これはあなたが使用したと思われるものです) は、実際にはあなたが望むものではありません。1 項目のレコード配列を作成するだけです。

>>> 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

sortそれを知って、argsortレコード配列を語彙的にソートすることも役立つかもしれません。また、 lexsortもあります。使用例lexsort:

>>> random_idx = numpy.random.permutation(range(12))
>>> a = numpy.array(a)[random_idx]
>>> b = numpy.array(b)[random_idx]
>>> sorted_idx = numpy.lexsort((b, a))
>>> a[sorted_idx]
array([0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 6])
>>> b[sorted_idx]
array([1, 2, 1, 2, 1, 4, 7, 9, 4, 8, 1, 1])

レコード配列のソート:

>>> 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')])
于 2012-08-08T16:28:42.530 に答える
1

これは私のために働く:

>>> 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 への引数が配列と同じ dtype を持つようにすることだと思います。しようZ.searchsorted((3, 7))とすると、セグメンテーション違反が発生します。

于 2012-08-08T17:29:52.303 に答える
0

これを行う興味深い方法があります(ただし、ecatmurの答えのようにO(log(n))ではなくO(n)であると信じているため、最も効率的な方法ではありませんが、よりコンパクトです):

np.searchsorted(a + 1j*b, a_val + 1j*b_val)

例:

>>> 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
于 2012-08-08T16:27:56.197 に答える
0

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)
于 2012-08-08T16:10:31.003 に答える
0

または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
于 2012-08-08T16:42:52.760 に答える