Najlepszym sposobem w twoim konkretnym przypadku byłaby po prostu zmiana dwóch kryteriów na jedno kryterium:
dists[abs(dists - r - dr/2.) <= dr/2.]
Tworzy tylko jedną tablicę logiczną i moim zdaniem jest łatwiejszy do odczytania, ponieważ mówi, że znajduje się dist
w obrębie dr
lub r
? (Chociaż przedefiniowałbym to, r
aby być centrum twojego regionu zainteresowania zamiast na początku, więc r = r + dr/2.
) Ale to nie odpowiada na twoje pytanie.
Odpowiedź na twoje pytanie:
tak naprawdę nie potrzebujesz, where
jeśli próbujesz tylko odfiltrować elementy dists
, które nie pasują do twoich kryteriów:
dists[(dists >= r) & (dists <= r+dr)]
Ponieważ &
da ci elementarny and
(nawiasy są konieczne).
Lub, jeśli where
z jakiegoś powodu chcesz użyć , możesz zrobić:
dists[(np.where((dists >= r) & (dists <= r + dr)))]
Dlaczego:
Przyczyną tego nie jest to, że np.where
zwraca listę indeksów, a nie tablicę logiczną. Próbujesz dostać się and
między dwiema listami liczb, które oczywiście nie mają oczekiwanych wartości True
/ False
. Jeśli obie wartości są a
i , to zwraca . Więc powiedzenie czegoś takiego po prostu ci da . Oto akcja:b
True
a and b
b
[0,1,2] and [2,3,4]
[2,3,4]
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]),)
Na przykład to, co spodziewałeś się porównać, to po prostu tablica boolowska
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)
Teraz możesz wywołać np.where
połączoną tablicę boolowską:
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. ])
Lub po prostu zindeksuj oryginalną tablicę tablicą logiczną, używając fantazyjnego indeksowania
In [241]: dists[(dists >= r) & (dists <= r + dr)]
Out[241]: array([ 5. , 5.5, 6. ])
np.logical_and
. Dzięki!Jedna interesująca rzecz, na którą należy zwrócić uwagę; zwykły sposób używania OR i AND również będzie działał w tym przypadku, ale z niewielką zmianą. Zamiast "and" i zamiast "or", użyj raczej Ampersand (&) i operatora potoku (|) i zadziała.
Kiedy używamy „i” :
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()
Kiedy używamy Ampersand (&) :
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')
Tak samo jest w przypadku, gdy próbujemy zastosować wiele filtrów w przypadku pand Dataframe. Teraz uzasadnienie tego ma coś wspólnego z operatorami logicznymi i operatorami bitowymi, a dla lepszego zrozumienia tego samego, proponuję przejść przez tę odpowiedź lub podobne pytania i odpowiedzi w przepływie stosu.
AKTUALIZACJA
Użytkownik zapytał, dlaczego istnieje potrzeba podania (ar> 3) i (ar <6) w nawiasach. Cóż, o to chodzi. Zanim zacznę mówić o tym, co się tutaj dzieje, trzeba wiedzieć o pierwszeństwie operatorów w Pythonie.
Podobnie jak w przypadku BODMAS, Python również daje pierwszeństwo temu, co powinno być wykonane jako pierwsze. Elementy w nawiasach są wykonywane jako pierwsze, a następnie do pracy dochodzi operator bitowy. Poniżej pokażę, co się dzieje w obu przypadkach, gdy używasz i nie używasz "(", ")".
Przypadek 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)
Ponieważ nie ma tu nawiasów, operator bitowy (
&
) jest tu zdezorientowany, że o co prosisz go, aby uzyskać logiczne AND of, ponieważ w tabeli pierwszeństwa operatorów, jeśli widzisz,&
ma pierwszeństwo przed operatorami<
lub>
. Oto tabela od najniższego do najwyższego priorytetu.To nie jest nawet wykonanie
<
i>
działanie i prosi, aby wykonać operację logiczną AND. Dlatego właśnie podaje ten błąd.Teraz do przypadku 2:
Jeśli użyjesz wspornika, wyraźnie zobaczysz, co się stanie.
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)
Dwie tablice True i False. I możesz łatwo wykonywać na nich operacje logiczne AND. Co daje ci:
np.where( array([False, True, True, False, False, True, False, False]), 'yo', ar)
A reszta wiecie, np. Gdzie, dla podanych przypadków, gdziekolwiek True, przypisuje pierwszą wartość (tj. Tutaj 'yo'), a jeśli False, drugą (czyli tutaj zachowując oryginał).
To wszystko. Mam nadzieję, że dobrze wyjaśniłem pytanie.
źródło
()
wokół(ar>3)
i(ar>6)
?Lubię używać
np.vectorize
do takich zadań. Rozważ następujące:>>> # 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.
Możesz także użyć
np.argwhere
zamiastnp.where
dla wyraźnego wydruku. Ale to twoja decyzja :)Mam nadzieję, że to pomoże.
źródło
Próbować:
np.intersect1d(np.where(dists >= r)[0],np.where(dists <= r + dr)[0])
źródło
To powinno działać:
Najbardziej elegancki sposób ~~
źródło
Próbować:
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))
Dane wyjściowe: (tablica ([2, 3]),)
Aby uzyskać więcej informacji, zobacz Funkcje logiczne .
źródło
Opracowałem ten prosty przykład
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]
źródło