준비
본 글에서는 데이터 분석시 필요한 데이터만 뽑아내는 색인 기능에 대해 실습합니다.
Numpy 가 주로 이용되며 개념 이해가 필요한 경우 전 글을 먼저 읽고 오시는 것을 추천드립니다.
색인과 슬라이싱
실습에 앞서 numpy 를 불러오고 arange (생성 함수)로 ndarray 를 생성합니다.
import numpy as np
arr = np.arange(10)
arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
브로드 캐스팅
arr[2:6] = 10
arr
array([ 0, 1, 10, 10, 10, 10, 6, 7, 8, 9])
대용량 데이터 처리가 목적이기에 복사를 하지 않고 원본 배열에 그대로 적용됩니다.
ten = arr[2:6]
ten[0:2] = 1010
arr
array([ 0, 1, 1010, 1010, 10, 10, 6, 7, 8, 9])
2차원 배열에서 인덱스 값은 1차원 배열입니다.
arr2 = np.array([[1,2,3],[4,5,6],[7,8,9]])
arr2[0]
array([1, 2, 3])
아래 두 표현은 동일한 결과를 반환합니다.
print(arr2[0][2])
print(arr2[0, 2])
print(arr2[0][2] == arr2[0, 2])
3
3
True
다차원 배열에서 마지막 색인을 생략하면 한 차원이 낮은 ndarray 가 됩니다.
arr3 = np.array([[[1,2,3,],[4,5,6]],[[7,8,9],[10,11,12]]])
arr3[0]
array([[1, 2, 3],
[4, 5, 6]])
copy 함수는 배열을 복사합니다.
원본 배열로부터 미치는 영향이 없게됩니다.
before = arr3[0].copy()
before
array([[1, 2, 3],
[4, 5, 6]])
아래처럼 중간 생략 색인이 가능합니다.
arr4 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(arr4)
print('- - -')
print(arr4[:2, 1:])
print('- - -')
print(arr4[:2][1:])
[[1 2 3]
[4 5 6]
[7 8 9]]
- - -
[[2 3]
[5 6]]
- - -
[[4 5 6]]
전체 축을 쓰면 원 차원(2차원)의 슬라이스를 얻을 수 있습니다.
arr4[:, :1] = 0
arr4
array([[0, 2, 3],
[0, 5, 6],
[0, 8, 9]])
불리언 색인
불리언으로 정의된 배열을 이용해 특정 조건에 해당하는 값을 가져오는 기능입니다.
먼저 두 개의 ndarray 를 생성합니다.
names = np.array(['Kim','Park','Kim','Kim','Choi','Kim','Jang','Song'])
data = np.random.randn(8,4) # 평균 0, 표준편차 1의 표준 정규분표 난수
print(names)
print('- - -')
print(data)
['Kim', 'Park', 'Kim', 'Kim', 'Choi', 'Kim', 'Jang', 'Song']
- - -
[[-0.53129446, -0.85261132, 1.53546679, -0.21280095],
[ 1.06509228, 0.45707734, -0.11924993, -0.26531921],
[ 1.15588226, -0.17372763, -1.11814896, 0.38045904],
[ 0.03339984, 1.18180965, 1.33530373, 0.83534962],
[-0.21945494, 0.8535551 , 0.48525176, -1.02971634],
[-0.14385928, -0.03412531, 0.33021612, 0.5282004 ],
[ 0.4871977 , -0.7526478 , 0.41970448, 0.44282802],
[ 0.79896261, 0.70078435, 0.12456365, -0.9561594 ]]
이름이 'Park' 또는 'Choi' 인 것만 가져옵니다.
mask = (names == 'Park') | (names == 'Choi')
mask
array([False, True, False, False, True, False, False, False])
불리언 배열에 대응하는 두 번째와 다섯 번째 로우만 출력됩니다.
data[mask]
array([[ 1.06509228, 0.45707734, -0.11924993, -0.26531921],
[-0.21945494, 0.8535551 , 0.48525176, -1.02971634]])
팬시 색인
정수형 배열을 사용하는 색인 기능입니다.
팬시 색인에서는 깊은 복사가 일어나 원본 데이터에는 손상이 없습니다.
arr = np.empty((8,4))
for i in range(8):
arr[i] = i
arr
array([[0., 0., 0., 0.],
[1., 1., 1., 1.],
[2., 2., 2., 2.],
[3., 3., 3., 3.],
[4., 4., 4., 4.],
[5., 5., 5., 5.],
[6., 6., 6., 6.],
[7., 7., 7., 7.]])
특정한 순서로 로우를 선택할 수 있습니다.
arr[[4,3,0,6]]
array([[4., 4., 4., 4.],
[3., 3., 3., 3.],
[0., 0., 0., 0.],
[6., 6., 6., 6.]])
축 변환
기본적인 축 변환에 대해서 알아봅니다.
arr = np.arange(24).reshape((4, 6))
arr
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
전치는 ndarray.T 를 이용합니다.
arr.T
array([[ 0, 6, 12, 18],
[ 1, 7, 13, 19],
[ 2, 8, 14, 20],
[ 3, 9, 15, 21],
[ 4, 10, 16, 22],
[ 5, 11, 17, 23]])
transpose 함수도 거의 동일한 작업을 처리합니다.
arr = np.arange(16).reshape((2,2,4))
print(arr)
print('- - -')
print(arr.transpose((2,1,0)))
[[[ 0 1 2 3]
[ 4 5 6 7]]
[[ 8 9 10 11]
[12 13 14 15]]]
- - -
[[[ 0 8]
[ 4 12]]
[[ 1 9]
[ 5 13]]
[[ 2 10]
[ 6 14]]
[[ 3 11]
[ 7 15]]]
Quiz
Q. 오늘 배운 색인 두 가지는?
A. 불리언 색인, 팬시 색인
Q. Numpy 의 여집합 표현 두 가지는?
A. "!=" 과 "~ ( )"
Q. Ndarray 의 로우와 컬럼 수를 바꾸는 속성은?
A. reshape
정답
문제의 의도와는 조금 다르지만 동적으로 처리가 가능한 함수로 코드를 작성했습니다.
def program(name):
names = np.array(['Kim','Park','Kim','Kim','Choi','Kim','Jang','Song'])
numbers = np.array([[10,12,17,13,14,11,16,15],[12,11,14,13,17,15,16,10]])
arr = numbers.T[names == name]
return '당첨' if arr[0, 0] == arr[0, 1] else '꽝'
name = input('이름 입력: ')
result = program(name)
print(result)
먼저 numbers 배열의 행과 열의 위치를 바꾸고 불리언 색인을 통해 대응하는 데이터를 arr 변수에 할당했습니다.
그리고 arr 은 2차원 배열이기 때문에 [0, 0] 그리고 [0, 1] 위치의 값을 비교함으로써 당첨 여부를 파악할 수 있습니다.
🙏 감사합니다
수업을 진행해주신 선린인터넷고등학교 이모션 동아리의 안유빈 선배님께 감사드립니다.
읽어주셔서 감사합니다.
😍 댓글