기능이 여러 조건 인 Numpy


132

dists라는 거리 배열이 있습니다. 두 값 사이의 dists를 선택하고 싶습니다. 이를 위해 다음 코드 줄을 작성했습니다.

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

그러나 이것은 조건에 대해서만 선택합니다

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

임시 변수를 사용하여 순차적으로 명령을 수행하면 정상적으로 작동합니다. 위의 코드가 작동하지 않는 이유는 무엇이며 어떻게 작동합니까?

건배

답변:


203

특정 경우 에 가장 좋은 방법은 두 가지 기준을 하나의 기준으로 변경하는 것입니다.

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

그것은 하나 개의 부울 배열을 생성하고, 내 의견으로는, 그것이 말하는 때문에 쉽게 읽을 수 있다 dist내에서 dr또는 r? (하지만 r처음부터 관심 지역의 중심으로 재정의하고 싶지만 r = r + dr/2.) 그러나 귀하의 질문에 대답하지 않습니다.


귀하의 질문에 대한 답변 : 기준에 맞지 않는 요소를 필터링하려고하는 경우
실제로 필요 하지 않습니다.wheredists

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

&는 요소별로 요소를 제공 하기 때문에 and(괄호가 필요합니다).

또는 where어떤 이유로 사용하려면 다음을 수행하십시오.

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

이유 :
작동하지 않는 이유 np.where는 부울 배열이 아닌 인덱스 목록을 반환 하기 때문 입니다. and두 숫자 목록 사이 를 가져 오려고하는데 물론 True/ False값 이 없습니다 . 경우 ab모두 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]),)

예를 들어 비교하려고 한 것은 단순히 부울 배열이었습니다.

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)

이제 np.where결합 된 부울 배열을 호출 할 수 있습니다 .

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. ])

또는 멋진 색인 생성을 사용하여 원래 배열을 부울 배열로 색인화합니다.

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

61

받아 들여진 대답은 문제를 충분히 설명했습니다. 그러나 여러 조건을 적용하기위한 Numpythonic 방식이 많을수록 numpy 논리 함수 를 사용하는 입니다. 이 ase에서는 다음을 사용할 수 있습니다 np.logical_and.

np.where(np.logical_and(np.greater_equal(dists,r),np.greater_equal(dists,r + dr)))

11

여기서 한 가지 흥미로운 점은 다음과 같습니다. 이 경우 ORAND 를 사용하는 일반적인 방법 도 작동하지만 약간의 변경이 있습니다. "and"대신 "or"대신 Ampersand (&)Pipe Operator (|) 를 사용하면 작동합니다.

'and'를 사용할 때 :

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

앰퍼샌드 (&)를 사용할 때 :

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

팬더 데이터 프레임의 경우 여러 필터를 적용하려고 할 때도 마찬가지입니다. 이제이 논리는 논리 연산자 및 비트 연산자와 관련이 있으며 그에 대한 더 많은 이해를 위해이 답변 또는 유사한 Q / A를 스택 오버 플로우로 진행하는 것이 좋습니다 .

최신 정보

사용자가 괄호 안에 (ar> 3) 및 (ar <6)을 제공해야하는 이유가 무엇인지 물었습니다. 여기에 문제가 있습니다. 여기서 무슨 일이 일어나고 있는지 이야기하기 전에 파이썬에서 연산자 우선 순위에 대해 알아야합니다.

BODMAS에 관한 것과 유사하게, 파이썬은 또한 먼저 수행해야 할 것에 우선권을줍니다. 괄호 안의 항목이 먼저 수행 된 다음 비트 연산자가 작동합니다. "(", ")"를 사용하고 사용하지 않을 때 두 경우 모두에서 발생하는 상황을 아래에서 보여 드리겠습니다.

사례 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)

더 괄호 여기가 없기 때문에, 비트 단위 연산자 ( &) 당신도 그것을 요구하는 어떤 논리적 얻을 것으로 여기 혼란스러워지고 AND 연산자 우선 순위 테이블에 당신이 볼 경우 때문에,의, &보다 우선 순위가 주어집니다 <또는 >운영자. 다음은 가장 낮은 우선 순위에서 가장 높은 우선 순위까지의 표입니다.

여기에 이미지 설명을 입력하십시오

심지어 <and >연산을 수행하지 않고 논리 AND 연산을 수행하라는 요청을 받고 있습니다. 그래서 그 오류가 발생합니다.

다음 링크를 확인하여 자세한 내용을 알아볼 수 있습니다. 연산자 우선 순위

이제 사례 2 :

대괄호를 사용하면 어떻게되는지 명확하게 알 수 있습니다.

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)

True와 False의 두 배열. 또한 논리적 AND 연산을 쉽게 수행 할 수 있습니다. 어느 것이 당신에게줍니다 :

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

np.where는 주어진 경우에, True가 어디든지 첫 번째 값 (예 : 'yo')을 할당하고 False이면 다른 값 (예 : 여기에서 원본 유지)을 할당합니다.

그게 다야. 쿼리를 잘 설명했으면합니다.


1
왜 넣어해야합니까 ()주위 (ar>3)(ar>6)?
RTrain3k

정말 좋은 질문입니다. 지구상에서 무엇이 필요하다고 스스로 생각해야했던 것은 좋은 질문입니다. 그래서 나는 동료에게 물었고 우리는 지금 당신을위한 해결책이 있다고 amd에 대해 이야기했습니다. 그것을 UPDATE로 답에 넣으십시오. 정말 간단하지만 실제로 이해하기는 어렵습니다.
Amit Amola

RTrain3k 업데이트를 확인하십시오. 귀하의 질문에 답변했습니다.
Amit Amola

5

나는 np.vectorize그러한 작업 에 사용 하고 싶습니다 . 다음을 고려하세요:

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

선명한 출력 np.argwhere대신에 사용할 수도 있습니다 np.where. 그러나 그것은 당신의 전화입니다 :)

도움이 되길 바랍니다.


2

시험:

np.intersect1d(np.where(dists >= r)[0],np.where(dists <= r + dr)[0])

2

이것은 작동해야합니다 :

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

가장 우아한 방법 ~~


2

시험:

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

출력 : (배열 ([2, 3]),)

자세한 내용 은 논리 기능 을 참조하십시오.


0

이 간단한 예제를 해결했습니다.

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]

6
이 경우 반복 할 필요가 없습니다. NumPy에는 부울 인덱싱이 있습니다.
M456
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.