python numpy.where ()는 어떻게 작동합니까?


94

나는 numpy문서를 가지고 놀고 파헤 치고 있으며 마법을 발견했습니다. 즉 나는 다음에 대해 이야기하고 있습니다 numpy.where().

>>> x = np.arange(9.).reshape(3, 3)
>>> np.where( x > 5 )
(array([2, 2, 2]), array([0, 1, 2]))

어떻게 내부적으로 당신이 같은 x > 5것을 메소드 에 전달할 수 있다는 것을 어떻게 달성 합니까? 나는 그것이 관련이 있다고 생각 __gt__하지만 자세한 설명을 찾고 있습니다.

답변:


75

x> 5와 같은 것을 메소드에 전달할 수 있다는 것을 내부적으로 어떻게 달성합니까?

짧은 대답은 그렇지 않다는 것입니다.

numpy 배열에 대한 모든 종류의 논리 연산은 부울 배열을 반환합니다. (즉 __gt__, __lt__등은 모두 주어진 조건이 참인 부울 배열을 반환합니다).

x = np.arange(9).reshape(3,3)
print x > 5

수율 :

array([[False, False, False],
       [False, False, False],
       [ True,  True,  True]], dtype=bool)

이것이 numpy 배열 if x > 5:이면 ValueError를 일으키는 것과 같은 이유 x입니다. 단일 값이 아니라 True / False 값의 배열입니다.

또한 numpy 배열은 부울 배열로 인덱싱 할 수 있습니다. 예를 x[x>5]산출 [6 7 8]이 경우.

솔직히, 실제로 필요한 경우는 매우 드물지만 numpy.where부울 배열이있는 인덱스 만 반환합니다 True. 일반적으로 간단한 부울 인덱싱으로 필요한 작업을 수행 할 수 있습니다.


10
다만 지적하고 numpy.where처음 2 '작동 모드', 하나 개의 반환을해야합니까 indices, condition is True및 선택적 매개 변수 경우 xy(동일 모양 존재 condition, 그것은에서 값을 반환합니다, 또는 모양 캐스트 가능한!)를 x할 때 condition is True, 그렇지 않으면에서 y. 따라서 이것은 where더 다양 하게 만들고 더 자주 사용할 수 있습니다. 감사합니다
2011

1
over 또는 의 __getitem__구문을 사용하는 경우에 오버 헤드가 발생할 수도 있습니다 . 슬라이싱도 지원해야하기 때문에 약간의 오버 헤드가 있습니다. Python Pandas 데이터 구조로 작업하고 매우 큰 열을 논리적으로 인덱싱 할 때 눈에 띄는 속도 차이를 보았습니다. 이러한 경우에, 당신은 다음 슬라이스가 필요하지 않은 경우 와 더 나은 사실이다. []numpy.wherenumpy.take__getitem__takewhere
ely

24

이전 답변 은 다소 혼란 스럽습니다. 귀하의 진술이 사실 인 위치 (모두)를 제공합니다.

그래서:

>>> a = np.arange(100)
>>> np.where(a > 30)
(array([31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
       48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
       65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
       82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
       99]),)
>>> np.where(a == 90)
(array([90]),)

a = a*40
>>> np.where(a > 1000)
(array([26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
       43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
       60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
       77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
       94, 95, 96, 97, 98, 99]),)
>>> a[25]
1000
>>> a[26]
1040

list.index ()의 대안으로 사용하지만 다른 용도도 많이 있습니다. 2D 배열과 함께 사용한 적이 없습니다.

http://docs.scipy.org/doc/numpy/reference/generated/numpy.where.html

New Answer 그 사람은 좀 더 근본적인 것을 묻고있는 것 같습니다.

질문은 함수 (예 : 어디서)가 요청 된 내용을 알 수있는 무언가를 구현할 수있는 방법이었습니다.

먼저 비교 연산자를 호출하면 흥미로운 일이 발생합니다.

a > 1000
array([False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True`,  True,  True,  True,  True,  True,  True,  True,  True,  True], dtype=bool)`

이것은 "__gt__"메소드를 오버로딩함으로써 수행됩니다. 예를 들면 :

>>> class demo(object):
    def __gt__(self, item):
        print item


>>> a = demo()
>>> a > 4
4

보시다시피 "a> 4"는 유효한 코드였습니다.

여기에서 오버로드 된 모든 함수의 전체 목록과 문서를 얻을 수 있습니다. http://docs.python.org/reference/datamodel.html

놀라운 것은이 작업을 수행하는 것이 얼마나 간단한 지입니다. 파이썬의 모든 작업은 이러한 방식으로 수행됩니다. a> b는 a와 동일합니다. gt (b)!


3
예를 들어 내가 할 수없는 -이 비교 연산자 오버로딩은하지만 더 복잡한 논리적 표현과 잘 작동하지 않는 것 np.where(a > 30 and a < 50)또는 np.where(30 < a < 50)그 논리 AND 꽤 의미가 논리 값의 두 배열의 평가하려고 끝 때문이다. 이러한 조건을 작성하는 방법이 np.where있습니까?
davidA apr

@meowsqueaknp.where((a > 30) & (a < 50))
tibalt

np.where ()가 예제에서 목록을 반환하는 이유는 무엇입니까?
Andreas Yankopolus

0

np.where호출 된 numpy ndarray의 차원과 동일한 길이의 튜플을 반환하고 (즉, ndim) 튜플의 각 항목은 조건이 True 인 초기 ndarray에있는 모든 값의 인덱스의 numpy ndarray입니다. (치수와 모양을 혼동하지 마세요)

예를 들면 :

x=np.arange(9).reshape(3,3)
print(x)
array([[0, 1, 2],
      [3, 4, 5],
      [6, 7, 8]])
y = np.where(x>4)
print(y)
array([1, 2, 2, 2], dtype=int64), array([2, 0, 1, 2], dtype=int64))


y는 2이므로 길이가 2 인 튜플입니다. 튜플의 x.ndim첫 번째 항목에는 4보다 큰 모든 요소의 행 번호가 포함되고 두 번째 항목에는 4보다 큰 모든 항목의 열 번호가 포함됩니다. 보시다시피 [1,2,2 , 2]는 5,6,7,8의 행 번호에 해당하고 [2,0,1,2]는 5,6,7,8의 열 번호에 해당합니다. ndarray는 첫 번째 차원 (행 방향 ).

비슷하게,

x=np.arange(27).reshape(3,3,3)
np.where(x>4)


x는 3 차원을 가지므로 길이가 3 인 튜플을 반환합니다.

그러나 잠깐, np.where에 더 많은 것이 있습니다!

두 개의 추가 인수가 추가 될 때 np.where; 위의 튜플에서 얻은 모든 쌍별 행-열 조합에 대해 대체 작업을 수행합니다.

x=np.arange(9).reshape(3,3)
y = np.where(x>4, 1, 0)
print(y)
array([[0, 0, 0],
   [0, 0, 1],
   [1, 1, 1]])
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.