일부 값보다 큰 Python NumPy Array의 모든 요소를 ​​대체하십시오.


190

2D NumPy 배열을 가지고 있으며 임계 값 T 이상인 255.0의 모든 값을 바꾸고 싶습니다. 내 지식으로는 가장 기본적인 방법은 다음과 같습니다.

shape = arr.shape
result = np.zeros(shape)
for x in range(0, shape[0]):
    for y in range(0, shape[1]):
        if arr[x, y] >= T:
            result[x, y] = 255
  1. 가장 간결하고 파이썬적인 방법은 무엇입니까?

  2. 이 작업을 수행하는 더 빠른 방법 (간결하고 덜 간결한 방법)이 있습니까?

이것은 사람 머리의 MRI 스캔을위한 창 / 레벨 조정 서브 루틴의 일부입니다. 2D numpy 배열은 이미지 픽셀 데이터입니다.


답변:


332

가장 빠르고 간결한 방법은 NumPy의 내장 Fancy 색인 생성을 사용하는 것입니다. ndarraynamed 가 있으면 다음과 같이 arr모든 요소 >255를 값 x으로 바꿀 수 있습니다 .

arr[arr > 255] = x

내 컴퓨터에서 500 x 임의의 매트릭스로 0.5을 5로 바꾸고 평균 7.59ms가 걸렸습니다.

In [1]: import numpy as np
In [2]: A = np.random.rand(500, 500)
In [3]: timeit A[A > 0.5] = 5
100 loops, best of 3: 7.59 ms per loop

3
이것은 OP에서와 같이 배열 arr을 작성하는 대신 기존 배열을 수정합니다 result.
askewchan

1
수정하지 않고 A새 배열을 만들어 이를 수행 할 수있는 방법이 있습니까?
나트륨 질산염

n = 2에 대해 a [2], a [4], a [6], a [8] .....과 같이 주어진 n의 배수 인 인덱스에서 값을 변경하려면 어떻게해야합니까?
lavee_singh

100 루프, 루프 당 3 :
2.22ms 중 최고

5
참고 : 데이터가 파이썬 목록에 있으면 작동하지 않습니다. numpy 배열 ( np.array([1,2,3]) 이어야합니다.
mjp

46

당신은 실제로 다른 배열을 원하기 때문에 , 그리고 그렇지 않으면,이 간단하게 할 수 있습니다 :arrarr < 255255

result = np.minimum(arr, 255)

보다 일반적으로, 하한 및 / 또는 상한의 경우 :

result = np.clip(arr, 0, 255)

그냥 더 복잡 255 값, 또는 무언가에 액세스하려면, @ mtitan8의 대답은 더 일반적이지만, np.clipnp.minimum(또는 np.maximum) 좋네요 훨씬 빨리 케이스 :

In [292]: timeit np.minimum(a, 255)
100000 loops, best of 3: 19.6 µs per loop

In [293]: %%timeit
   .....: c = np.copy(a)
   .....: c[a>255] = 255
   .....: 
10000 loops, best of 3: 86.6 µs per loop

제자리에서 수행하려면 (즉, arr대신에 수정 result) out매개 변수를 사용할 수 있습니다 np.minimum.

np.minimum(arr, 255, out=arr)

또는

np.clip(arr, 0, 255, arr)

( out=함수는 함수 정의와 동일한 순서로 인수되므로 선택 사항입니다.)

전체 수정의 경우 부울 색인 생성 속도가 빨라지지만 (복사본을 별도로 만든 다음 수정하지 않아도 됨) 여전히 다음과 같이 빠르지는 않습니다 minimum.

In [328]: %%timeit
   .....: a = np.random.randint(0, 300, (100,100))
   .....: np.minimum(a, 255, a)
   .....: 
100000 loops, best of 3: 303 µs per loop

In [329]: %%timeit
   .....: a = np.random.randint(0, 300, (100,100))
   .....: a[a>255] = 255
   .....: 
100000 loops, best of 3: 356 µs per loop

비교를 위해 최소값과 최대 값으로 값을 제한 clip하려면 다음과 같이 두 번 수행하지 않아도됩니다.

np.minimum(a, 255, a)
np.maximum(a, 0, a)

또는,

a[a>255] = 255
a[a<0] = 0

1
귀하의 완전한 의견에 감사드립니다. 그러나이 경우에는 np.clip과 np.minimum이 필요한 것 같지 않습니다 .OP에서는 임계 값 T와 대체 값 (255)이 반드시 동일하지는 않습니다. 번호. 그러나 나는 여전히 당신에게 철저한 투표를했습니다. 다시 감사합니다.
NLi10Me

n = 2에 대해 a [2], a [4], a [6], a [8] .....과 같이 주어진 n의 배수 인 인덱스에서 값을 변경하려면 어떻게해야합니까?
lavee_singh

@lavee_singh, 그렇게하기 위해 슬라이스의 세 번째 부분을 사용할 수 있습니다. 일반적으로 무시됩니다 : a[start:stop:step]배열의 요소를 startto stop에서 제공하지만 모든 요소 대신 모든 요소 만 필요합니다 step(무시한 경우 1기본적으로 ). 모든 a[::2] = 0
짝수

고맙지 만 간단한 목록을 알고 있지만 numpy.array에서 작동하는지 여부를 알지 못했지만 이와 같은 것이 필요했습니다.
lavee_singh

14

나는 당신이 where기능 을 사용하여 이것을 가장 빨리 달성 할 수 있다고 생각합니다 :

예를 들어 numpy 배열에서 0.2보다 큰 항목을 찾고 0으로 대체하면 다음과 같습니다.

import numpy as np

nums = np.random.rand(4,3)

print np.where(nums > 0.2, 0, nums)

10

numpy.putmask 사용을 고려할 수 있습니다 .

np.putmask(arr, arr>=T, 255.0)

Numpy의 내장 인덱싱과의 성능 비교는 다음과 같습니다.

In [1]: import numpy as np
In [2]: A = np.random.rand(500, 500)

In [3]: timeit np.putmask(A, A>0.5, 5)
1000 loops, best of 3: 1.34 ms per loop

In [4]: timeit A[A > 0.5] = 5
1000 loops, best of 3: 1.82 ms per loop

8

다른 방법은 np.place전체 교체를 수행하고 다차원 배열과 함께 작동하는 것입니다.

import numpy as np

# create 2x3 array with numbers 0..5
arr = np.arange(6).reshape(2, 3)

# replace 0 with -10
np.place(arr, arr == 0, -10)

이것이 내가 처음 만났기 때문에 내가 사용한 솔루션입니다. 이 답변과 위의 선택된 답변 사이에 큰 차이가 있는지 궁금합니다. 어떻게 생각해?
jonathanking

매우 제한적인 테스트에서 위의 np.place 코드는 허용되는 답변의 직접 색인 작성 방법보다 2 배 느리게 실행됩니다. np.place가 더 최적화 될 것이라고 생각했기 때문에 놀라운 일이지만 직접 색인 작성에 더 많은 노력을 기울일 것으로 생각됩니다.
Shital Shah

필자의 경우 np.place내장 방법에 비해 속도가 느 렸지만 의견 에서 반대 주장 제기되었습니다.
riyansh.legend

3

유연성을 높이기 위해 &, |및 / 또는을 사용할 수도 있습니다 .

5와 10 사이의 값 : A[(A>5)&(A<10)]

10보다 크거나 5보다 작은 값 : A[(A<5)|(A>10)]

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.