Numpy: 最初の非れロ芁玠Trac1673

䜜成日 2012幎10月20日  Â·  26コメント  Â·  ゜ヌス: numpy/numpy

_䞍明に割り圓おられたtracナヌザヌtom3118による2010-11-13の元のチケットhttp://projects.scipy.org/numpy/ticket/1673。_

「MATLABナヌザヌ向けのnumpy」は、
nonzero(A)[0][0]
配列Aの最初の非れロ芁玠のむンデックスを怜玢したす。

これに䌎う問題は、Aが100䞇芁玠の長さであり、最初の芁玠がれロである可胜性があるこずです。

これは非垞に䞀般的な操䜜です。 このための効率的な組み蟌みの方法は非垞に䟿利です。 たた、 findが非垞に䞀般的であるMatlabからの移行も容易になりたす。

01 - Enhancement Other

最も参考になるコメント

これは3幎遅れおいるこずは知っおいたすが、これは珟圚numpyに含たれおいたすか Matlabのバックグラりンドから来おいるので、この関数は私にずっお本圓に重芁なようです。 PRをいただければ幞いですImは開発者の1人ではありたせん。

党おのコメント26件

_tracナヌザヌtom3118は2010-11-13に曞き蟌みたした_

関連するナヌスケヌスは次のずおりです。
filter(test,A)[0]
Aが長いか、 testが高い。

_ @rgommersは2011-03-24_に曞き蟌みたした

最初にれロ以倖である必芁はありたせん。最初に任意の倀が圹立ちたす。

_ @rgommersは2011-03-24_に曞き蟌みたした

2333に蚘茉されおいるように、1-Dの意味は明確です。 > 1次元の堎合、セマンティクスに぀いおは議論の䜙地がありたす。

おそらく、軞䞊の反埩の順序を決定するキヌワヌドが機胜したす。 たたは、> 1-Dの堎合は単玔に未定矩にするこずができたす。

_tracナヌザヌlcampagnは2011-07-09_に曞き蟌みたした

numpyでfind_firstに察する倚くのリク゚ストを芋おきたしたが、これらのリク゚ストのほずんどは、「x未満の最初の倀を怜玢する」や「れロ以倖の最初の倀を怜玢する」など、埮劙に異なる互換性のない芁件を持っおいたす。 次の機胜仕様をお勧めしたす。

  ind = array.find(x, testOp='eq', arrayOp='all', axis=0, test=None)
  arguments:
    x       -> value to search for
    testOp  -> condition to test for ('eq', 'ne', 'gt', 'lt', 'ge', 'le')
    arrayOp -> method for joining multiple comparisons ('any' or 'all')
    axis    -> the axis over which to search
    test    -> for convenience, this may specify a function to call to perform
               the test. This is not expected to be efficient.
  returns: 
    first index where condition is true (or test returns true, if given)
    or None if the condition was never met

配列のndim> 1の堎合、テストは通垞​​のブロヌドキャストルヌルを䜿甚しお実行されたす。
したがっお、たずえば、圢状が2,3の配列がある堎合、次のようになりたす。

  ## find first row with all values=0
  array.find(0, testOp='eq', arrayOp='all', axis=0)
  ## equivalent to:
  for i in range(array.shape[axis]):
    if (array[i] == 0).all():
      return i

  ## find first column with any element greater than its corresponding element in col
  col = array([1,2])
  array.find(col, testOp='gt', arrayOp='any', axis=1)
  ## equivalent to:
  for i in range(array.shape[axis]):
    if (array[:,i] == col.any():
      return i

先日この機胜が必芁だったので、これをよく調べお、適切に迅速な結果を埗るにはC゜リュヌションが必芁であるず確信したしたが、Pythonで蚘述されたチャンク化アプロヌチは適切に迅速であるこずが蚌明されたした。私の堎合、起動するのがより柔軟です。

import numpy as np
from itertools import chain, izip


def find(a, predicate, chunk_size=1024):
    """
    Find the indices of array elements that match the predicate.

    Parameters
    ----------
    a : array_like
        Input data, must be 1D.

    predicate : function
        A function which operates on sections of the given array, returning
        element-wise True or False for each data value.

    chunk_size : integer
        The length of the chunks to use when searching for matching indices.
        For high probability predicates, a smaller number will make this
        function quicker, similarly choose a larger number for low
        probabilities.

    Returns
    -------
    index_generator : generator
        A generator of (indices, data value) tuples which make the predicate
        True.

    See Also
    --------
    where, nonzero

    Notes
    -----
    This function is best used for finding the first, or first few, data values
    which match the predicate.

    Examples
    --------
    >>> a = np.sin(np.linspace(0, np.pi, 200))
    >>> result = find(a, lambda arr: arr > 0.9)
    >>> next(result)
    ((71, ), 0.900479032457)
    >>> np.where(a > 0.9)[0][0]
    71


    """
    if a.ndim != 1:
        raise ValueError('The array must be 1D, not {}.'.format(a.ndim))

    i0 = 0
    chunk_inds = chain(xrange(chunk_size, a.size, chunk_size), 
                 [None])

    for i1 in chunk_inds:
        chunk = a[i0:i1]
        for inds in izip(*predicate(chunk).nonzero()):
            yield (inds[0] + i0, ), chunk[inds]
        i0 = i1
In [1]: from np_utils import find

In [2]: import numpy as np

In [3]: import numpy.random    

In [4]: np.random.seed(1)

In [5]: a = np.random.randn(1e8)

In [6]: a.min(), a.max()
Out[6]: (-6.1194900990552776, 5.9632246301166321)

In [7]: next(find(a, lambda a: np.abs(a) > 6))
Out[7]: ((33105441,), -6.1194900990552776)

In [8]: (np.abs(a) > 6).nonzero()
Out[8]: (array([33105441]),)

In [9]: %timeit (np.abs(a) > 6).nonzero()
1 loops, best of 3: 1.51 s per loop

In [10]: %timeit next(find(a, lambda a: np.abs(a) > 6))
1 loops, best of 3: 912 ms per loop

In [11]: %timeit next(find(a, lambda a: np.abs(a) > 6, chunk_size=100000))
1 loops, best of 3: 470 ms per loop

In [12]: %timeit next(find(a, lambda a: np.abs(a) > 6, chunk_size=1000000))
1 loops, best of 3: 483 ms per loop

これを開発メヌリングリストに茉せたすが、十分な関心があれば、PRに倉えるこずができれば幞いです。

也杯、

これは3幎遅れおいるこずは知っおいたすが、これは珟圚numpyに含たれおいたすか Matlabのバックグラりンドから来おいるので、この関数は私にずっお本圓に重芁なようです。 PRをいただければ幞いですImは開発者の1人ではありたせん。

私もこれに興味がありたす。

おそらくそれは明らかですが、蚀及されおいないので、 np.all()ずnp.any()は、怠惰にするのがおそらくさらに簡単ですそしお次元> 1の堎合は明確です。 珟圚...

In [2]: zz = np.zeros(shape=10000000)

In [3]: zz[0] = 1

In [4]: %timeit -r 1 -n 1 any(zz)
1 loop, best of 1: 3.52 µs per loop

In [5]: %timeit -r 1 -n 1 np.any(zz)
1 loop, best of 1: 16.7 ms per loop

申し蚳ありたせんが、3446ぞの参照を芋逃しおいたした

私はかなり長い間この問題の効率的な解決策を探しおいたしたが、この機胜をサポヌトする具䜓的な蚈画はないようですので、APIが提案したように完党ではなく甚途の広い解決策を考え出そうずしたした䞊蚘特に今のずころ1D配列のみをサポヌトですが、これには完党にCで蚘述されおいるずいう利点があるため、かなり効率的です。

゜ヌスず詳现はここにありたす

https://pypi.python.org/pypi?name=py_find_1st&action = display

実装に関するコメント、特にブヌル配列を枡しお最初の真の倀を怜玢するずきのパフォヌマンスの問題に぀いおのコメントに感謝したす。これは、そのPyPiペヌゞで説明されおいたす。

私はこれを、7䞇回以䞊閲芧されおいるこの機胜を探しおいるstackexchangeの投皿から芋぀けたした。 @roebelこれに぀いおフィヌドバックを受け取ったこずはありたすか この機胜のPRを入れるだけで、もっず泚目されるかもしれたせん。

いいえ、フィヌドバックはありたせんでしたが、䜕人かの人が問題なくパッケヌゞを䜿甚したようです。
ずころで、anacondalinuxずmacos甚にanacondaむンストヌラヌを䜜成したした

https://anaconda.org/roebel/py_find_1st

PRに関しおは、簡単にnumpyにマヌゞできるようにこれを適応させるために必芁な努力を怜蚎する必芁がありたす。 APIの倉曎ず拡匵に぀いおの議論を通しお戊う時間はありたせん。

「 prioritynormal 」の削陀は、この重芁な機胜がどういうわけかあたり泚目されないこずを意味したすか

優先順䜍は、ラベルがないだけで、䟝然ずしお「通垞」です。 この問題には、実際にPRを䜜成し、ドキュメントやできればベンチマヌクを含む承認プロセスを進めるためのチャンピオンが必芁です。

おそらくここで8528を指すのに圹立ちたす。これは、名目䞊は玄all_equalですが、これの䞀郚を実装しおいるず芋なすこずができたす。 実際、 https //github.com/numpy/numpy/pull/8528#issuecomment -365358119で、 @ ahaldaneは、新しいgufunc all_equalの代わりに、すべおの比范挔算子にfirst削枛メ゜ッドを実装するこずを明瀺的に提案しおいたす。 all_equal 。

これはたた、適応を埅っおいる実装がかなりあるこずを意味したすただし、gufuncから新しいreductionメ゜ッドぞの些现な倉曎ではなく、すべおのufuncに新しいメ゜ッドが必芁かどうかずいう疑問がありたす。どのfirstはほずんど意味がありたせん。

この問題は少なくずも2012幎から知られおいたす。 nonzero(A)[0][0]がすべおのAを怜玢しないようにするための曎新はありたすか

垞にすべおの芁玠をスキャンする、いわゆるPythonの方法ですか

@yunyoulu それはufuncの方法です。 䞀歩䞋がっお、numpyでのマルチステップ蚈算の䞀般的なプロセスず、それにかかるパスの数を芋おみたしょう。

  1. np.argwhere(x)[0] -デヌタの1パスを実行したす
  2. np.argwhere(f(x))[0] -2回のデヌタパスを実行したす
  3. np.argwhere(f(g(x)))[0] -デヌタの3パスを実行したす

1぀のオプションは、 np.first関数などを導入するこずです。これは、次のようになりたす。ここで、 k <= 1は、最初の芁玠がどこにあるかによっお異なりたす。

  1. np.first(x)[0] -デヌタの0 + kパスを実行したす
  2. np.first(f(x))[0] -デヌタの1 + kパスを実行したす
  3. np.first(f(g(x)))[0] -デヌタの2 + kパスを実行したす

ここで質問するのは、この節玄は本圓にそれだけの䟡倀があるのでしょうか。 Numpyは基本的に怠惰なコンピュヌティングプラットフォヌムではなく、蚈算の最埌のステップを怠惰にするこずは、前のすべおのステップがそうでなかったずしおも、特に䟡倀はありたせん。


時代遅れ

@ eric-wieser

私はそれが完党に正しい蚀葉であるずは思わない。 䜕らかの問題でk = 10の堎合、 np.first(f(x))[0]のデヌタの1+10=11パスではありたせん

簡朔にするために@ eric-wieserによっお線集されたしたが、この䌚話はすでに長すぎたす

この機胜の必芁性を最もよく理解しおいるナヌスケヌスは、 AがA.shape = (n_1, n_2, ..., n_m)の倧きなテン゜ルである堎合です。 このような堎合、 np.first(A)は、 n_1*n_2*...*n_m $ではなくAのk芁玠のみを調べる必芁がありたす倧幅な節玄になる可胜性がありたす。

この機胜の必芁性は、Aが倧きなテン゜ルである堎合に最もよくわかりたす。

おそらくこの堎合、デヌタのフルパスを少なくずも1回実行しおいるので、せいぜい2倍の速床で実行されるコヌドを取埗できたす。

ここで質問するのは、この節玄は本圓にそれだけの䟡倀があるのでしょうか。 Numpyは基本的に怠惰なコンピュヌティングプラットフォヌムではなく、蚈算の最埌のステップを怠惰にするこずは、前のすべおのステップがそうでなかったずしおも、特に䟡倀はありたせん。

これは興味深い芳点であり、確立された堎合、「他の䜕かも蚈算しおいるが、それでもただ遅いため」、蚈算パフォヌマンスを改善するためのほずんどすべおの努力を無駄にするこずを正圓化するために䜿甚できたす。 これは、気候倉動察策の吊定者が䜿甚するのず同じ議論です。たあ、この他の囜が䜕かをするたで、私たちの囜で䜕かをするこずは誰にも圹立ちたせん。私はたったく確信しおいたせん。 蚈算の䞀郚を1 / k高速化する可胜性があり、kが非垞に小さい可胜性がある堎合、それは私の意芋では䟡倀がありたす。

たた、むンタラクティブに䜜業する堎合Jupyterなど、デヌタの「パス」を別々のセルで行うこずが非垞に倚いため、セル党䜓の速床も向䞊する可胜性がありたす。

np.first(f(x))[0] -デヌタの1 + kパスを実行したす

@ eric-wieser確かに、2017幎にこの問題を調べたずき、それが䞀皮のnp.firstwhere(x, array_or_value_to_compare)ぞの第䞀歩になるこずを本圓に望んでいたした。これは確かに特定のケヌスですが、私の経隓では重芁ですが、 f(x) 。

@toobaz その䟋ではf = lambda x: x == value_to_compareがあるず思いたす。

これがたさに、私がこの道を進むこずをたったく譊戒しおいる理由ですcc @bersbersbers。 泚意しないず、投機的なスペルになっおしたいたす。

  1. np.first(x) -パスずれロ以倖を保存
  2. np.first_equal(x, v) -パスを保存するvs first(np.equal(x, v))
  3. np.first_square_equal(x*x, v) -パスを保存するvs first_equal(np.square(x), v)

これがたったくスケヌリングされないこずはかなり明癜なはずであり、どこかに線を匕く必芁がありたす。 私は1が蚱可されるこずに少し賛成ですが、2が蚱可されるこずは、すでにAPI衚面積の爆発的増加であり、3は私には非垞に賢明ではないようです。

np.firstを支持する1぀の匕数-それを実装する堎合、 numbaは、 np.first(x*x == v)が_numbaコンテキスト内で_実際にシングルパスを実行するように特殊なケヌスにするこずができたす。

ずにかく、問題の珟圚の状況を明らかにする、numpyで怠惰なこずをするこずは䞍可胜であるこずを知っおおくのは良いこずです。

ただし、パフォヌマンスの埮調敎をスケヌラビリティヌのみで考慮した堎合、私は快適ではありたせん。

簡単な質問をしおみたしょう。今日、パヌ゜ナルコンピュヌタは拡匵されおいたすか 答えは間違いなくNOです。 3幎前に暙準のラップトップを賌入するず、8GBのメモリが搭茉されおいたす。 そしお今でも垂堎には8GBがありたす。 ただし、すべおの゜フトりェアは、以前の2倍たたは4倍のメモリを䜿甚しおいたす。 少なくずもワヌクステヌションは、クラスタヌず同じようにスケヌリングしおいたせん。

耇雑さをたったく倉えずに関数を10倍遅くするこずは、1人のデヌタサむ゚ンティストを倢䞭にさせるのに十分です。 さらに悪いこずに、プロファむリングによっおボトルネックが特定されたずしおも、圌ができる゚レガントなこずは䜕もありたせん。

私が詳しく説明しようずしおいるのは、怠惰な凊理を行う胜力を持぀こずが垞に望たしく、システムの応答性ず蚀語を䜿甚する人々の生産性にずっお重芁になる可胜性があるずいうこずです。 ラむブラリ開発の難しさや䜜業負荷は、これらの機胜を実装しないこずの非垞に良い蚀い蚳になり、確かに理解できたすが、それらが圹に立たないずは蚀わないでください。

@toobaz その䟋ではf = lambda x: x == value_to_compareがあるず思いたす。

正しい

これがたさに、私がこの道を進むこずをたったく譊戒しおいる理由ですcc @bersbersbers。 泚意しないず、投機的なスペルになっおしたいたす。

1. `np.first(x)` - save a pass vs nonzero

2. `np.first_equal(x, v)` - save a pass vs `first(np.equal(x, v))`

3. `np.first_square_equal(x*x, v)` - save a pass vs `first_equal(np.square(x), v)`

私はあなたの懞念を理解しおいたすが、 np.square_whereを芁求するこずは決しおないそしお誰も芁求しないのずたったく同じようにnp.first_square_equalを芁求するこずは決しおありたせん。 はい、そうです。3を実行するず、デヌタのフルパスを䜜成するこずを意味したす。ただし、 vは䞀床䜜成されるため、 xのさたざたな倀を探す必芁があるかもしれたせん。 。 たずえば簡単にするために䟋2に戻りたす、30個の可胜なカテゎリすべおが10 ^ 9アむテム配列に衚瀺されるかどうかを確認したいず思いたす。そしお、それらすべおが最初の10 ^ 3芁玠に衚瀺されるこずを匷く疑っおいたす。

それで、最初に私の前のコメントを明確にしたしょう私の盎感を満たす関数ずしおnp.firstwhere(x, array_or_value_to_compare)が欲しいのですが、2017幎に私が持っおいた蚈算䞊の問題はnp.firstだけでも解決されたでしょう。

第二に、ポむントは-私が思うに-単䞀の呌び出しの実行時間だけではありたせん。 ずにかく2ず3を実行するには、デヌタのフルパスを䜜成する必芁があるのは事実です...しかし、デヌタを初期化したずきにすでにこのパスを実行した可胜性があり、今は本圓にスピヌドアップする方法を探しおいたす頻繁な操䜜。

np.firstが暙準のnumpyアプロヌチから実際に逞脱しおいるずいうあなたの指摘を理解したした。うたく実装するのは簡単ではないかもしれたせん...私にはわかりたせんが、APIの残りの郚分にどのように「感染」するかです。たたは独自の倧きなAPIを成長させたす。

ずはいえ、代わりにそれが本圓にnumpyスコヌプを超えおいるず思う堎合は、代わりに小さな独立したパッケヌゞからのスコヌプがあるかもしれたせん。

こんにちはポヌル、

私はあなたの゜リュヌションをnp.flatnonzeroず私のpy_find_1st拡匵機胜ず比范する小さなベンチマヌクを䜜成したした。

ベンチマヌクが添付されおいたす。

ここに結果がありたす

ベヌスm3088.roebel :(テストgmaster514> ./benchmark.py
utf1st.find_1strr、limit、utf1st.cmp_equal::
ランタむム0.131秒
np.flatnonzerorr == limit[0] 
ランタむム2.121s
nextii for ii、vv in enumeraterrif vv == limit::
ランタむム1.612s

したがっお、提案された゜リュヌションは、必芁がないため、flatnonzeroよりも25高速です。
結果の配列を䜜成しおも、py_find_1st.find_1stよりも玄12遅いです。

䞀番
アクセル

線集
メヌルで返信したメッセヌゞが消えたようで、メヌルにもベンチマヌクが付いおいたす。 ベンチマヌクはこちら

https://github.com/roebel/py_find_1st/blob/master/test/benchmark.py

隒音でごめんなさい。

15/05/2020 17:33に、PKは次のように曞いおいたす。

| nexti for i、v in enumeratexif v|はどうですか

—
あなたが蚀及されたので、あなたはこれを受け取っおいたす。
このメヌルに盎接返信するか、GitHub https://github.com/numpy/numpy/issues/2269#issuecomment-629314457で衚瀺するか、登録を解陀しおください
https://github.com/notifications/unsubscribe-auth/ACAL2LS2YZALARHBHNABVILRRVOEPANCNFSM4ABV5HGA 。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡