(파이썬 머신러닝 완벽 가이드 Chap 01.03)
arange() - 0부터 함수 인자값의 -1까지 연속값으로 초기화
zeros() - 0으로 초기화
ones() - 1로 초기화
테스트용으로 데이터를 만들거나 대규모의 데이터를 일괄적으로 초기화해야 할 경우에 사용된다.
sequence_array = np.arange(10)
print(sequence_array)
print(sequence_array.dtype, sequence_array.shape)
[0 1 2 3 4 5 6 7 8 9]
int32 (10,)
arange의 syntax는 아래와 같다
arange([start, ]stop, [step, ]dtype=None)
default 값은 stop 값이고, start 값, step 값도 부여할 수 있으며, dtype을 지정하는 것도 가능하다.
array_start = np.arange(4, 10)
print(array_start)
array_step = np.arange(4, 10, 2)
print(array_step)
array_step_only = np.arange(10, step = 2)
print(array_step_only)
array_dtype = np.arange(10, dtype=float)
print(array_dtype)
print(array_dtype.dtype, array_dtype.shape)
output
[4 5 6 7 8 9]
[4 6 8]
[0 2 4 6 8]
[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
float64 (10,)
zeros() 는 함수 인자로 튜플 형태의 shape 값을 입력하면 모든 값을 0으로 채운 해당 shape의 ndarray를 반환한다
ones() 는 함수 인자로 튜플 형태의 shape 값을 입력하면 모든 값을 1으로 채운 해당 shape의 ndarray를 반환한다
두 함수 모두 dtype을 지정해주지 않으면 float64 형의 dtype을 가진 ndarray로 반환한다.
zero_array_default = np.zeros((3,2))
print(zero_array_default)
print(zero_array_default.dtype, zero_array_default.shape)
zero_array_dtype = np.zeros((3, 2), dtype = 'int32')
print(zero_array_dtype)
print(zero_array_dtype.dtype, zero_array_dtype.shape)
one_array_default = np.ones((3,2))
print(one_array_default)
print(one_array_default.dtype, one_array_default.shape)
one_array_dtype = np.ones((3, 2), dtype = 'int32')
print(one_array_dtype)
print(one_array_dtype.dtype, one_array_dtype.shape)
output
[[0. 0.]
[0. 0.]
[0. 0.]]
float64 (3, 2)
[[0 0]
[0 0]
[0 0]]
int32 (3, 2)
[[1. 1.]
[1. 1.]
[1. 1.]]
float64 (3, 2)
[[1 1]
[1 1]
[1 1]]
int32 (3, 2)
reshape() 메서드는 ndarray를 특정 차원 및 크기로 변환한다.
아래의 예제는 0~19 까지의 1차원 ndarray를
4 rows x 5 columns (2차원)
5 rows x 4 columns (2차원)
2 rows x 5 columns x 2 heights (3차원)
으로 변환하는 예제이다
array1 = np.arange(20)
print('array1:\n', array1)
array2 = array1.reshape(4, 5)
print('array2:\n', array2)
array3 = array1.reshape(5, 4)
print('array3:\n', array3)
array4 = array1.reshape(2, 5, 2)
print('array4:\n', array4)
output
array1:
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
array2:
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]
array3:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]
[16 17 18 19]]
array4:
[[[ 0 1]
[ 2 3]
[ 4 5]
[ 6 7]
[ 8 9]]
[[10 11]
[12 13]
[14 15]
[16 17]
[18 19]]]
당연한 얘기지만, shape 사이즈가 맞지 않으면 변경할 수 없고, reshape() 는 오류를 발생시킨다
reshape() 를 사용할 때, 인자를 -1로 적용하면 고정된 나머지 인자에 따라서 shape를 자동 적용해준다.
(물론 shape 사이즈가 호환돼야 가능하다)
아까의 예제에서 인자를 -1로 바꿔서 실행하면 아래와 같다
array1 = np.arange(20)
print('array1:\n', array1)
array2 = array1.reshape(-1, 5)
print('array2:\n', array2)
array3 = array1.reshape(5, -1)
print('array3:\n', array3)
array4 = array1.reshape(2, -1, 2)
print('array4:\n', array4)
output
array1:
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
array2:
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]
array3:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]
[16 17 18 19]]
array4:
[[[ 0 1]
[ 2 3]
[ 4 5]
[ 6 7]
[ 8 9]]
[[10 11]
[12 13]
[14 15]
[16 17]
[18 19]]]
이때 array4에서 유의할 점이 있는데, -1로 지정하는 unknown dimension 은 오직 하나만 지정가능하다
array4 = array1.reshape(2, -1, -1) (x)
array4 = array1.reshape(2, -1, 2) (o)
-1 인자는 reshape(-1, 1), reshape(-1,) 과 같은 형태로 자주 사용된다.
reshape(-1, 1) 은 원본 ndarray가 어떤 형태라도 2차원이고, 여러개의 로우를 가지되 반드시 1개의 칼럼을 가진 ndarray로 변환됨을 보장한다.
reshape(-1,) 는 원본 ndarray가 어떤 형태라도 1차원으로 변환됨을 보장한다.
여러개의 ndarray를 stack이나 concat으로 결합할 때 형태를 통일하기 위해 사용된다.
아래의 예제는 reshape(-1, 1) 를 이용해 1차원을 2차원으로, 3차원을 2차원으로 변환한다.
(ndarray는 tolist() 메서드를 이용해 리스트 자료형으로 변환할 수 있는데, print를 이용할 때 시각적으로 더 이해하기 쉽게 바꾸기 위해 쓴다.)
array1 = np.arange(8)
array3d = array1.reshape((2, 2, 2))
print('array3d:\n', array3d.tolist())
# 3차원 ndarray를 2차원 ndarray로 변환
array5 = array3d.reshape(-1, 1)
print('array5:\n', array5.tolist())
print('array5 shape:', array5.shape)
# 1차원 ndarray를 2차원 ndarray로 변환
array6 = array1.reshape(-1, 1)
print('array6:\n', array6.tolist())
print('array6 shape:', array6.shape)
# 3차원 ndarray를 1차원 ndarray로 변환
array7 = array3d.reshape(-1,)
print('array7:\n', array7.tolist())
print('array7 shape:', array7.shape)
output
array3d:
[[[0, 1], [2, 3]], [[4, 5], [6, 7]]]
array5:
[[0], [1], [2], [3], [4], [5], [6], [7]]
array5 shape: (8, 1)
array6:
[[0], [1], [2], [3], [4], [5], [6], [7]]
array6 shape: (8, 1)
array7:
[0, 1, 2, 3, 4, 5, 6, 7]
array7 shape: (8,)
ndarray 객체에 해당하는 위치의 인덱스 값을 []안에 입력하면 된다.
# 1부터 9까지의 1차원 ndarray 생성
array1 = np.arange(start = 1, stop = 10)
print('array1:', array1)
value = array1[2]
print('value:', value)
print(type(value))
# 뒤에서 부터 인덱싱할 수 있다
value_backward1 = array1[-1]
value_backward2 = array1[-3]
print('value_backward1:', value_backward1)
print('value_backward2:', value_backward2)
# 수정도 가능하다
array1[5] = 22
print('array1:', array1)
output
array1: [1 2 3 4 5 6 7 8 9]
value: 3
<class 'numpy.int32'>
value_backward1: 9
value_backward2: 7
array1: [ 1 2 3 4 5 22 7 8 9]
다차원 ndarray에서 단일 값을 추출하는 예제.
1차원 ndarray를 생성하고, 2차원의 3x3 shape 으로 변환 후, [axis0, axis1]을 통해 2차원 ndarray에서 데이터 추출
(axis0 = row, axis1 = column)
array1d = np.arange(start=1, stop=10)
array2d = array1d.reshape(3,3)
print(array2d)
print('[0,0] :', array2d[0,0] )
print('[0,1] :', array2d[0,1] )
print('[1,0] :', array2d[1,0] )
print('[2,2] :', array2d[2,2] )
output
[[1 2 3]
[4 5 6]
[7 8 9]]
[0,0] : 1
[0,1] : 2
[1,0] : 4
[2,2] : 9
3차원 이상의 ndarray는 직관적으로 row와 column을 생각하며 indexing 하기 어렵다.
따라서, indexing의 순서는 차원이 높은 쪽에서 낮은 쪽으로 (바깥쪽에서 안쪽으로) 진행된다고 알고 있어야 한다.
array1d = np.arange(start=1, stop=25)
array3d = array1d.reshape(2, 3, 4)
print(array3d)
print('array3d[0,0,0]', array3d[0,0,0])
print('array3d[0,1,1]', array3d[0,1,1])
print('array3d[1,2,3]', array3d[1,2,3])
output
[[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
[[13 14 15 16]
[17 18 19 20]
[21 22 23 24]]]
array3d[0,0,0] 1
array3d[0,1,1] 6
array3d[1,2,3] 24
array1 = np.arange(start=1, stop=10)
print(array1)
array3 = array1[0:3]
print(array3)
print(type(array3))
output
[1 2 3 4 5 6 7 8 9]
[1 2 3]
<class 'numpy.ndarray'>
':' 기호 앞/뒤에 시작/종료 인덱스를 생략하면 자동으로 맨 처음/맨 마지막 인덱스로 간주.
array1 = np.arange(start=1, stop=10)
array4 = array1[:3]
print(array4)
array5 = array1[3:]
print(array5)
array6 = array1[:]
print(array6)
output
[1 2 3]
[4 5 6 7 8 9]
[1 2 3 4 5 6 7 8 9]
2차원도 동일하게 slicing 할 수 있으나, 각 axis를 ','로 구분하는 것만 다르다.
또한, axis에 따라 slicing과 indexing을 혼용할 수 있다.
array1d = np.arange(start=1, stop=10)
array2d = array1d.reshape(3,3)
print('array2d:\n',array2d)
print('array2d[0:2, 0:2] \n', array2d[0:2, 0:2])
print('array2d[1:3, 0:3] \n', array2d[1:3, 0:3])
print('array2d[1:3, :] \n', array2d[1:3, :])
print('array2d[:, :] \n', array2d[:, :])
print('array2d[:2, 1:] \n', array2d[:2, 1:])
print('array2d[:2, 0] \n', array2d[:2, 0]) # Slicing과 Indexing을 혼용
output
array2d:
[[1 2 3]
[4 5 6]
[7 8 9]]
array2d[0:2, 0:2]
[[1 2]
[4 5]]
array2d[1:3, 0:3]
[[4 5 6]
[7 8 9]]
array2d[1:3, :]
[[4 5 6]
[7 8 9]]
array2d[:, :]
[[1 2 3]
[4 5 6]
[7 8 9]]
array2d[:2, 1:]
[[2 3]
[5 6]]
array2d[:2, 0]
[1 4]
2차원 ndarray에서 뒤에 오는 index를 없애면 1차원 ndarray를 반환.
3차원 ndarray에서 뒤에 오는 index를 없애면 2차원 ndarray를 반환.
첫번째 axis만 indexing 되고 그 뒤의 axis는 그 차원 그대로 호출되는 것이다.
array1d = np.arange(start=1, stop=25)
array2d = array1d.reshape(4,6)
array3d = array1d.reshape(2,3,4)
print(array2d[0])
print(array2d[1])
print(array3d[0])
print(array3d[1])
print('array2d[0] shape:', array2d[0].shape, 'array2d[1] shape:', array2d[1].shape)
print('array3d[0] shape:', array3d[0].shape, 'array3d[1] shape:', array3d[1].shape)
output
[1 2 3 4 5 6]
[ 7 8 9 10 11 12]
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
[[13 14 15 16]
[17 18 19 20]
[21 22 23 24]]
array2d[0] shape: (6,) array2d[1] shape: (6,)
array3d[0] shape: (3, 4) array3d[1] shape: (3, 4)
리스트나 ndarray로 인덱스 집합을 지정하면 해당 위치의 인덱스에 해당하는 ndarray를 반환하는 인덱싱 방식.
array1d = np.arange(start=1, stop=10)
array2d = array1d.reshape(3,3)
print(array2d)
array3 = array2d[[0,1], 2]
print('array2d[[0,1], 2] => ',array3.tolist())
array4 = array2d[[0,2], 0:2]
print('array2d[[0,2], 0:2] => ',array4.tolist())
array5 = array2d[[0,1]]
print('array2d[[0,1]] => ',array5.tolist())
output
[[1 2 3]
[4 5 6]
[7 8 9]]
array2d[[0,1], 2] => [3, 6]
<class 'numpy.ndarray'>
array2d[[0,2], 0:2] => [[1, 2], [7, 8]]
array2d[[0,1]] => [[1, 2, 3], [4, 5, 6]]
array3 = array2d[[0,1], 2] 이라고 지정하면, array2d[0,2], array2d[1,2] 값을 모두 반환한다.
조건 필터링과 검색을 동시에 할 수 있다.
index를 지정하는 []내에 조건문을 그대로 기재하면, for loop/if esle문 보다 훨씬 간단하게 구현 가능.
array1d = np.arange(start=1, stop=10)
print(array1d)
# [ ] 안에 array1d > 5 라는 Boolean Indexing 을 적용
array3 = array1d[array1d > 5]
print('array1d > 5 인 값 :', array3)
output
[1 2 3 4 5 6 7 8 9]
array1d > 5 인 값 : [6 7 8 9]
ndarray 객체에 조건식을 할당하면 True, False로 이뤄진 ndarray 객체가 반환된다.
이를 다시 ndarray 안에 넣으면 True 값이 있는 인덱스로 변환되고, 해당되는 인덱스 위치의 데이터만 반환하게 된다.
boolean_indexing = array1d > 5
indexes = np.array([5, 6, 7, 8])
print(boolean_indexing)
print(indexes)
print(array1d[boolean_indexing], array1d[indexes])
output
[False False False False False True True True True]
[5 6 7 8]
[6 7 8 9] [6 7 8 9]