Ich habe eine Reihe von Entfernungen, die Dists genannt werden. Ich möchte Dists auswählen, die zwischen zwei Werten liegen. Ich habe dazu die folgende Codezeile geschrieben:

 dists[(np.where(dists >= r)) and (np.where(dists <= r + dr))]

Dies wählt jedoch nur für die Bedingung

 (np.where(dists <= r + dr))

Wenn ich die Befehle nacheinander mit einer temporären Variablen ausführe, funktioniert das einwandfrei. Warum funktioniert der obige Code nicht und wie kann ich ihn zum Laufen bringen?

Prost

181
user1654183 2 Mai 2013 im 21:03

8 Antworten

Beste Antwort

Der beste Weg in Ihrem speziellen Fall besteht darin, Ihre beiden Kriterien in ein Kriterium zu ändern:

dists[abs(dists - r - dr/2.) <= dr/2.]

Es wird nur ein boolesches Array erstellt und ist meiner Meinung nach einfacher zu lesen, da darin steht, dass dist innerhalb eines dr oder r? liegt (obwohl ich ' d Definieren Sie r neu, um anstelle des Anfangs das Zentrum Ihrer Interessenregion zu sein. r = r + dr/2.) Aber das beantwortet Ihre Frage nicht.


Die Antwort auf Ihre Frage:
Sie benötigen where nicht, wenn Sie nur versuchen, die Elemente von dists herauszufiltern, die nicht Ihren Kriterien entsprechen:

dists[(dists >= r) & (dists <= r+dr)]

Weil das & Ihnen ein elementweises and gibt (die Klammern sind notwendig).

Wenn Sie aus irgendeinem Grund where verwenden möchten, können Sie Folgendes tun:

 dists[(np.where((dists >= r) & (dists <= r + dr)))]

Warum:
Der Grund, warum es nicht funktioniert, ist, dass np.where eine Liste von Indizes zurückgibt, kein boolesches Array. Sie versuchen, and zwischen zwei Listen von Zahlen zu erhalten, die natürlich nicht die erwarteten True / False -Werte haben. Wenn a und b beide True Werte sind, gibt a and b b zurück. Wenn Sie also etwas wie [0,1,2] and [2,3,4] sagen, erhalten Sie nur [2,3,4]. Hier ist es in Aktion:

In [230]: dists = np.arange(0,10,.5)
In [231]: r = 5
In [232]: dr = 1

In [233]: np.where(dists >= r)
Out[233]: (array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19]),)

In [234]: np.where(dists <= r+dr)
Out[234]: (array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12]),)

In [235]: np.where(dists >= r) and np.where(dists <= r+dr)
Out[235]: (array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12]),)

Was Sie erwartet hatten, um zu vergleichen, war zum Beispiel einfach das boolesche Array

In [236]: dists >= r
Out[236]: 
array([False, False, False, False, False, False, False, False, False,
       False,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True], dtype=bool)

In [237]: dists <= r + dr
Out[237]: 
array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True, False, False, False, False, False,
       False, False], dtype=bool)

In [238]: (dists >= r) & (dists <= r + dr)
Out[238]: 
array([False, False, False, False, False, False, False, False, False,
       False,  True,  True,  True, False, False, False, False, False,
       False, False], dtype=bool)

Jetzt können Sie np.where für das kombinierte boolesche Array aufrufen:

In [239]: np.where((dists >= r) & (dists <= r + dr))
Out[239]: (array([10, 11, 12]),)

In [240]: dists[np.where((dists >= r) & (dists <= r + dr))]
Out[240]: array([ 5. ,  5.5,  6. ])

Oder indizieren Sie einfach das ursprüngliche Array mit dem booleschen Array mithilfe von ausgefallener Indizierung

In [241]: dists[(dists >= r) & (dists <= r + dr)]
Out[241]: array([ 5. ,  5.5,  6. ])
189
askewchan 4 Mai 2013 im 18:12

Das sollte funktionieren:

dists[((dists >= r) & (dists <= r+dr))]

Der eleganteste Weg ~~

2
Qhan 24 Jän. 2019 im 08:11

Versuchen:

import numpy as np
dist = np.array([1,2,3,4,5])
r = 2
dr = 3
np.where(np.logical_and(dist> r, dist<=r+dr))

Ausgabe: (Array ([2, 3]),)

Weitere Informationen finden Sie unter Logikfunktionen.

2
Xiong-Hui Chen 24 Juni 2019 im 08:17

Ich benutze gerne np.vectorize für solche Aufgaben. Folgendes berücksichtigen:

>>> # function which returns True when constraints are satisfied.
>>> func = lambda d: d >= r and d<= (r+dr) 
>>>
>>> # Apply constraints element-wise to the dists array.
>>> result = np.vectorize(func)(dists) 
>>>
>>> result = np.where(result) # Get output.

Sie können auch np.argwhere anstelle von np.where für eine klare Ausgabe verwenden. Aber das ist dein Anruf :)

Ich hoffe es hilft.

5
user4340135user4340135 9 Nov. 2017 im 06:32

Versuchen:

np.intersect1d(np.where(dists >= r)[0],np.where(dists <= r + dr)[0])
2
Alex Riley 31 Aug. 2015 im 18:33

Eine interessante Sache, auf die hier hingewiesen werden muss; In diesem Fall funktioniert auch die übliche Verwendung von ODER und UND , jedoch mit einer kleinen Änderung. Verwenden Sie anstelle von "und" und anstelle von "oder" lieber kaufmännisches Und (&) und Pipe Operator (|) , und es funktioniert.

Wenn wir 'und' verwenden:

ar = np.array([3,4,5,14,2,4,3,7])
np.where((ar>3) and (ar<6), 'yo', ar)

Output:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Wenn wir kaufmännisches Und (&) verwenden:

ar = np.array([3,4,5,14,2,4,3,7])
np.where((ar>3) & (ar<6), 'yo', ar)

Output:
array(['3', 'yo', 'yo', '14', '2', 'yo', '3', '7'], dtype='<U11')

Dies gilt auch für den Fall, dass bei Pandas Dataframe mehrere Filter angewendet werden sollen. Die Gründe dafür haben nun etwas mit logischen Operatoren und bitweisen Operatoren zu tun. Um dies besser zu verstehen, würde ich vorschlagen, diese durchzugehen Antwort oder ähnliche Fragen / Antworten im Stapelüberlauf.

AKTUALISIEREN

Ein Benutzer fragte, warum in der Klammer (ar> 3) und (ar <6) angegeben werden müssen. Nun, hier ist die Sache. Bevor ich darüber spreche, was hier passiert, muss man über die Priorität von Operatoren in Python Bescheid wissen.

Ähnlich wie bei BODMAS hat auch Python Vorrang vor dem, was zuerst ausgeführt werden sollte. Elemente in der Klammer werden zuerst ausgeführt, und dann kommt der bitweise Operator zur Arbeit. Ich werde unten zeigen, was in beiden Fällen passiert, wenn Sie "(", ")" verwenden und nicht verwenden.

Fall 1:

np.where( ar>3 & ar<6, 'yo', ar)
np.where( np.array([3,4,5,14,2,4,3,7])>3 & np.array([3,4,5,14,2,4,3,7])<6, 'yo', ar)

Da es hier keine Klammern gibt, wird der bitweise Operator (&) hier verwirrt, was Sie überhaupt von ihm verlangen, um ein logisches UND zu erhalten, denn in der Operator-Prioritätstabelle, wenn Sie sehen, ist & Vorrang vor < oder > Operatoren. Hier ist die Tabelle von der niedrigsten bis zur höchsten Priorität.

enter image description here

Es führt nicht einmal die Operationen < und > aus und wird aufgefordert, eine logische UND-Operation auszuführen. Deshalb gibt es diesen Fehler.

Weitere Informationen finden Sie unter folgendem Link: operator Vorrang

Nun zu Fall 2:

Wenn Sie die Halterung verwenden, sehen Sie deutlich, was passiert.

np.where( (ar>3) & (ar<6), 'yo', ar)
np.where( (array([False,  True,  True,  True, False,  True, False,  True])) & (array([ True,  True,  True, False,  True,  True,  True, False])), 'yo', ar)

Zwei Arrays von True und False. Und Sie können einfach logische UND-Operationen an ihnen ausführen. Welches gibt Ihnen:

np.where( array([False,  True,  True, False, False,  True, False, False]),  'yo', ar)

Und ruhen Sie sich aus, np.wo, für bestimmte Fälle, wo immer True, den ersten Wert zuweist (d. H. Hier 'yo') und wenn False, den anderen (d. H. Hier, das Original behalten).

Das ist alles. Ich hoffe ich habe die Abfrage gut erklärt.

5
Amit Amola 31 Jän. 2020 im 19:42

Ich habe dieses einfache Beispiel ausgearbeitet

import numpy as np

ar = np.array([3,4,5,14,2,4,3,7])

print [X for X in list(ar) if (X >= 3 and X <= 6)]

>>> 
[3, 4, 5, 4, 3]
0
kiriloff 2 Mai 2013 im 17:08

Da erklärte die akzeptierte Antwort das Problem sehr gut. Sie können auch numpy logische Funktionen verwenden, für die hier besser geeignet ist Mehrfachbedingung:

np.where(np.logical_and(np.greater_equal(dists,r),np.greater_equal(dists,r + dr)))
53
Kasramvd 14 Nov. 2017 im 15:18