2013-10-23 7 views
11

Ich habe ein Array von ganzen Zahlen und wollen wo das Array gleich einem Wert in einer Liste von mehreren Werten ist. Dies kann leicht erreicht werden, indem jeder Wert einzeln behandelt wird oder indem mehrere "oder" -Anweisungen in einer Schleife verwendet werden, aber ich habe das Gefühl, dass es einen besseren/schnelleren Weg geben muss, dies zu tun. Ich beschäftige mich eigentlich mit Arrays der Größe 4000x2000, aber hier ist eine vereinfachte Version des Problems:Finden Sie, wo ein numpy Array ist gleich einem Wert einer Liste von Werten

fake=arange(9).reshape((3,3)) 
array([[0, 1, 2], 
     [3, 4, 5], 
     [6, 7, 8]]) 
want=(fake==0)+(fake==2)+(fake==6)+(fake==8) 
print want 
array([[ True, False, True], 
     [False, False, False], 
     [ True, False, True]], dtype=bool) 

Was ich möchte, ist ein Weg, want aus einem einzigen Befehl zu bekommen beteiligt fake und die Liste der Werte [0,2,6,8] . Ich könnte den Befehl selbst schreiben, aber ich nehme an, dass es ein Paket gibt, das bereits enthalten ist, das wäre wesentlich schneller als wenn ich nur eine Funktion mit einer Schleife in Python geschrieben hätte.

Danke, -Adam

Antwort

14

Die Funktion numpy.in1d scheint zu tun, was Sie wollen. Die einzigen Probleme ist, dass es nur auf 1d Arrays arbeitet, so sollten Sie es wie folgt verwenden:

In [9]: np.in1d(fake, [0,2,6,8]).reshape(fake.shape) 
Out[9]: 
array([[ True, False, True], 
     [False, False, False], 
     [ True, False, True]], dtype=bool) 

Ich habe keine Ahnung, warum dies bis 1d Arrays beschränkt ist nur. Mit Blick auf seine source code, scheint es zunächst die beiden Arrays zu glätten, wonach es einige clevere Sortiertricks macht. Aber nichts würde verhindern, dass das Ergebnis am Ende wieder abgeflacht wird, so wie ich es hier von Hand machen musste.

+0

Hmm. Ich schrieb diese sehr einfache Funktion, diesen Job zu tun: \t 'def EqualsAny (ar, vals): \t out = Nullen (ar.shape, dtype = bool) \t für val in vals: \t out + = (ar == val) \t Rückkehr Bereich führt zur ich dachte, dass 'numpy.in1d' schneller sein würde, aber es dauert aber länger (für gleiches Ergebnis): \t' in [11]:% timeit EqualsAny (badlabels, smallnum) \t 1 Schlaufen, am besten von 3: 519 ms pro Schleife \t in [7]:% timeit in1d (badlabels, smallnum) .reshape (Badla bels.shape) \t 1 loops, best of 3: 871 ms pro Schleife' Sollte 'numpy.in1d' nicht viel schneller sein, da es in C geschrieben ist? Benütze ich '% Zeit 'nicht richtig? – arwright3

+0

Nein, 'in1d' ist nicht in c geschrieben, sondern in Python, siehe den Link zum Quellcode, den ich angegeben habe. Es benutzt verschiedene numpy Funktionen wie 'sort', die hoffentlich in C geschrieben sein sollten. Es hat sogar einen optimierten Algorithmus, wenn' vals' kurz ist, was Ihrer Lösung ziemlich ähnlich ist (aber mit '| =' anstelle von ' + = '). Ich weiß nicht, warum Ihre Version schneller ist, dies könnte von der Länge beider Eingaben abhängen. –

5

@ Bas Antwort ist die, die Sie wahrscheinlich suchen. Aber hier ist eine andere Art und Weise, es zu tun, numpy der mit vectorize Trick:

import numpy as np 
S = set([0,2,6,8]) 

@np.vectorize 
def contained(x): 
    return x in S 

contained(fake) 
=> array([[ True, False, True], 
      [False, False, False], 
      [ True, False, True]], dtype=bool) 

Die con dieser Lösung besteht darin, daß contained() für jedes Element aufgerufen wird (zB in Python-Raum), die so viel langsamer als ein rein- macht numpige Lösung.