IT/언어

[python/Numpy] Numpy 요소 바꾸는 함수

개발자 두더지 2021. 11. 28. 22:15
728x90

numpy.where()


 numpy.where()은 조건문을 만족하는 요소와 만족하지 않은 요소를 각각 지정한 숫자나 불 값으로 바꿔주는 함수이다. 기본 구문은 다음과 같다.

numpy.where(condition, x, y)

 condition에는 배열을 포함한 조건문을 넣고, condition이 참일 때는 x로 값을 바꾸고, 거짓일 경우는 y로 값을 치환한다.

 numpy.where()을 사용하여 배열의 짝수 요소를 0, 홀수 요소를 1로 치환해보자.

# NUMPY_WHERE

# In[1]

import numpy as np

# [[1 2 3]
#  [4 5 6]
#  [7 8 9]]
a = np.arange(1, 10).reshape(3, 3)

# 짝수는 0, 홀수는 1으로 치환한다.
b = np.where(a % 2 == 0, 0, 1)

print(b)

 결과는 다음과 같다.

[[1 0 1]
 [0 1 0]
 [1 0 1]]

 배열을 요소를 직접적으로 치환하는 것으로, b와 동일한 배열을 생성할 수 있다.

# In[2]

# [[1 2 3]
#  [4 5 6]
#  [7 8 9]]
c = np.arange(1, 10).reshape(3, 3)

# 조건문
condition = c % 2 == 0

# 조건을 만족하는 요소는 0로 바꾼다.
c[condition] = 0

# 조건을 만족하지 않는 요소는 1로 치환한다.
c[~condition] = 1

print(c)
[[1 0 1]
 [0 1 0]
 [1 0 1]]

 일반적으로는 이러한 작성법이 메모리 효율이 좋고, 처리도 빠르지만, numpy.where()는 원래의 배열을 변경하지 않고 새로운 배열을 생성하므로, 변수가 덮어씌어질 리스크를 피하기 위한 선택지이다.

 numpy.where()의 첫 번째 인수(condition) 만을 전달하면, 조건을 만족하는 요소의 인덱스 번호를 리턴한다. 다차원 배열에 적용하는 경우, 인덱스 번호는 1차원 배열으로 표시된다. 예를 들어, In[1] 로 정의한 배열 a의 각 요소의 인덱스는 아래의 그림과 같이 된다(그림의 빨간색 글씨가 인덱스 번호이다).

짝수가 되는 요소는 a[0][1], a[1][0], a[1][2], a[2][2]이다. axis = 0 방향과 axis = 1 방향의 인덱스 방향을 1차원 배열로 표시하면 각각 [0 1 1 2], [0 1 1 2]이 된다. 실제로 코드를 작성해서 확인해보자.

# In[3]

# 짝수 요소의 인덱스 번호를 얻어낸다.
d = np.where(a % 2 == 0)

print(d)
(array([0, 1, 1, 2], dtype=int32), array([1, 0, 2, 1], dtype=int32))

 

 

numpy.put()


 numpy.put()은 지정한 인덱스의 요소를 치환한다. 이 함수는 원래의 배열을 변경한다.

put(arr, indices, values, mode='raise')

 arr에는 치환 대상 배열, indices에는 인덱스, values에는 치환할 값 혹은 배열을 인수로 넣는다.

# NUMPY_PUT

# In[1]

import numpy as np

# [[1 1 1]
#  [1 1 1]
#  [1 1 1]]
array = np.ones((3, 3), dtype = np.int32)

# 0,2,4,6,8번째의 요소를 0으로 치환한다.
np.put(array, [0, 2, 4, 6, 8], 0)

print(array)
[[0 1 0]
 [1 0 1]
 [0 1 0]]

 옵션 인수 mode는 indices로 지정한 인덱스가 arr의 범위 외에 있는 경우의 리턴 값이다. 기본적으로는 raise이고, 에러를 반환하도록 되어 있다. 이 동작은 지극히 자연적이지만, 원하면 다른 리턴 값을 선택하는 것이 가능하다. 예를 들어, mode에 "clip"을 지정하면, indices가 범위 외인 경우 배열의 맨 끝의 요소가 치환된다.

# In[2]

# [1 1 1 1 1]
array = np.ones(5)

# 인덱스10은 배열의 범위 밖이므로 맨 끝에 요소를 0으로 치환한다.
np.put(array, 10, 0, 'clip')

print(array)
[1. 1. 1. 1. 0.]

 

 

numpy.place()


 numpy.place()는 조건에 맞는 요소를 지정한 요소로 바꾼다.

numpy.place(arr, mask, vals)

arr에는 배열, mask에는 arr와 동일한 사이즈의 불(bool) 배열, vals에는 1차원 시퀀스를 인수로 전달한다.  

# NUMPY_PLACE

# In[1]

import numpy as np

# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]
array = np.arange(1, 13).reshape(3, 4)

# 짝수(2로 나눠지는 수)를 0으로 바꾼다.
np.place(array, array % 2 == 0, 0)

print(array)
[[ 1  0  3  0]
 [ 5  0  7  0]
 [ 9  0 11  0]]

 인수 val에 리스트 등을 지정하여 여러 개의 요소를 한 번에 바꾸는 것도 가능하지만, 조건에 맞지 않은 요소는 그대로 둔다.

# In[2]

array = np.array([[1, 2, 3, 4, 1],
                  [5, 7, 8, 6, 9]])

# 3보다 큰 요소를 [1 0 0]로 치환한다.
np.place(array, array > 3, [1, 0, 0])

print(array)
[[1 2 3 1 1]
 [0 0 1 0 0]]

 

 

numpy.putmask()


 numpy.putmask()는 조건에 맞는 요소를 지정한 값으로 바꾼다. 이 함수는 원래의 배열을 변경한다.

putmask(a, mask, values)

 a에는 배열에 상응하는 옵션(ndarray나 list 등), masik에는 a와 동일한 사이즈의 bool 배열, valuse에는 치환할 값을 전달한다.

# NUMPY_PUTMASK

# In[1]

import numpy as np

# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]
array = np.arange(12).reshape(3, 4)

# 5보다 큰 요소는 그 값을 10배로 한다.
np.putmask(array, array > 5, array*10)

print(array)
[[  0   1   2   3]
 [  4   5  60  70]
 [ 80  90 100 110]]

 인수 values에 여러 개의 값을 전달하는 것이 가능하다.

# In[2]

# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]
array = np.arange(12).reshape(3, 4)

# 5보다 큰 요소는 [1 0 0]에 치환한다.
np.putmask(array, array > 5, [1, 0, 0])

print(array)
[[0 1 2 3]
 [4 5 1 0]
 [0 1 0 0]]

참고자료

https://python.atelierkobato.com/where/

728x90