파이썬 머신러닝 입문 공부일지 2. Numpy 기본 함수 공부 (2) 넘파이 배열 인덱싱, 슬라이싱, 정렬과 선형대수 연산
앞서 Numpy 넘파이의 기본 배열 함수에 대해서 알아보았습니다.
이번에는 선택자 함수인 인덱싱과 슬라이싱 그리고 정렬에 대한 것을 알아보겠습니다.
Numpy의 선택함수
인덱싱, 슬라이싱
ndarray 인덱싱
몇 번째 index 멤버에 접근한다는 인덱싱Indexing을 Numpy에서도 사용할 수 있습니다.
Numpy 배열의 indexing 의 종류는 다음과 같습니다.
- 특정 데이터만 추출 : 리스트, 튜플 등에서의 인덱싱과 동일. 숫자를 잘못 쓰면 값에 오류가 납니다.
- 슬라이싱Slicing : 리스트, 튜플에서의 슬라이싱과 동일. 숫자를 잘못 써도 오류가 나지는 않지만 결과는 기댓값과는 달라질 수 있습니다.
- 팬시 인덱싱Fancy Indexing : 일정한 인덱싱 집합을 리스트 또는 배열 형태로 지정해 해당 위치에 있는 값 반환합니다.
- 불리언 인덱싱Boolean Indexing : 특정 조건에 해당하는지 여부를 기반으로 배열 값 반환합니다. 과거의 필터와 비슷한 역할을 하며, 조건식을 기반으로 합니다.
인덱싱과 슬라이싱에 대해서는 아래의 파이썬 공부일지에서 작성한 것이 있습니다.
https://blue-dot.tistory.com/16
파이썬 공부일지 13. 리스트!
이제 파이썬으로 본격 코딩을 조금조금씩 맛보고 있는데, 진짜 재밌네요! 무에서 유를 만드는 느낌... 정말 망망대해에서 그물 짓고 있는 기분이에요.. 다시 또 시작해봅시당. 지금까지 공부한
blue-dot.tistory.com
하나씩 예제를 보면서 확인해볼게요.
array1 = np.arange(1, 10) # 범위를 적을 수 있으며 각각 1과 10의 값은 매개변수 지정하기를 통해 사용 가능합니다.
print(array1)
print("\n")
array1 = np.arange(start=1, stop=10) # 범위를 적을 수 있으며 각각 1과 10의 값은 매개변수 지정하기를 통해 사용 가능합니다.
print("첫 번째 : ", array1)
print("두 번째 : ", array1[2])
print("세 번째 : ", array1[4:7])
print("\n")
array2 = array1.reshape(3,3)
print(array2)
print(array2[1,0]) #리스트 중첩과 달리 배열은 이렇게 합니다.
#리스트 중첩의 경우 [1] 행의 [0]열을 볼때 [1][0]으로 작성하지만
#배열은 [1,0] 1행의 0열을 볼 때 이렇게 작성합니다.
아래는 위 인덱싱을 활용해서 가벼운 예제를 풀어볼게요.
1) 인덱싱 예제
# 1부터 12로 채워진 4행 3열짜리 배열을 만들고 6을 인덱싱
array1 = np.arange(1,13)
array2 = array1.reshape(4,3)
print(array2[1,2])
#코드를 이렇게 줄일 수도 있습니다.
print(np.arange(1,13).reshape(4,3)[1,2])
2) 슬라이싱 예제
슬라이싱은 복사본을 자르는 것입니다.
배열의 원본은 그대로 유지를 하고 슬라이싱을 하는 부분만 복사를 하게 됩니다.
즉, 원본을 훼손하지 않습니다.
슬라이싱을 할 때에는 값의 생략이 가능합니다. 첫 번째 값을 생략하면 처음부터, 뒤의 값을 생략하면 끝까지 슬라이싱을 합니다. [ : ] <- 일 경우 전체 복사가 됩니다.
array1 = np.arange(10)
print(array1[2:5]) # 2부터 4까지 슬라이싱을 하고 싶다면 마지막 숫자 + 1 로 슬라이싱을 합니다.
print(array1[:])
슬라이싱도 인덱싱과 똑같은 방식으로 적용할 수 있습니다.
array1 = np.arange(10)
print(array1[2:5]) # 2부터 4까지 슬라이싱을 하고 싶다면 마지막 숫자 + 1 로 슬라이싱을 합니다.
print(array1[:])
print("\n")
array1 = array1.reshape(5, 2) # 5행 2열로 변환
print(array1)
print("\n")
print(array1[0:2]) # 0행부터 2행 전까지 슬라이싱
코드의 마지막 줄에 있는 0행부터 2행 전까지의 슬라이싱을 한 배열에
다시금 슬라이싱을 할 수 있습니다.
print(array1[0:2, :1]) # 0행부터 2행 전까지 슬라이싱한 뒤에 전체 행에서 1행까지를 다시 슬라이싱
3) 팬시 인덱싱 예제
array1d = np.arange(start=1, stop=10)
array2d = array1d.reshape(3, 3)
print(array2d)
array3 = array2d[[0,1],2]
print("array3: ", array3)
array3 = array2d[[0,2],2]
print("array3: ", array3)
array3 = array2d[[0,2],2]
의 경우 0과 2번째 각각의 행에서 2번 인덱스의 값을 구하는 것이므로 3과 9가 인덱스 됩니다.
4) 필터 역할을 하는 배열의 불린 인덱싱 예제
# 필터 역할을 하는 배열의 불린 인덱싱
array1 = np.arange(3, 9)
# 인덱싱 기호 [] 안에서는 배열명을 요소로 취급
array1 = array1[array1 > 5]
print(array1)
array2 = np.array([True, True, True, True, False, True, False])
array2 = array2[array2]
print(array2)
행렬의 정렬
sort() , argsort()
- np.sort() : 본래의 행렬은 유지한 채 정렬 결과를 반환합니다.
- ndarray.sort() : 본래의 행렬의 정렬 후 결과 반환은 없습니다.
import numpy as np
org_array = np.array([3, 1, 9, 5])
print("원본 행렬 : ", org_array)
sort_array = np.sort(org_array) # 원 행렬은 유지
print("sort_array1 : ", sort_array)
sort_array2 = org_array.sort() # 원 행렬을 정렬
print("sort_array2 : ", sort_array2)
sort_array1_desc = np.sort(org_array)[::-1]
[ ::-1 ] 는 확장된 슬라이싱입니다.
기본적으로 슬라이싱(복사) 역할을 합니다. - 음수로 되어 있다면 내림차순(역순)으로 정렬한다는 뜻을 갖습니다.
음수 대신에 양수를 쓰거나 숫자를 안 쓸 경우 오름차순(순방향)으로 정렬됩니다.
sort_array1_desc = np.sort(org_array)[::-1]
print("역순으로 정렬되는지 확인 -> ", sort_array1_desc)
axis를 활용해서 행과 열 별로 오름차순 내림차순을 정렬해보겠습니다.
array2d = np.array([8,12,7,1]).reshape(2,2)
print(array2d)
print("\n")
# axis가 0일 때가 행(row)
# 오름차순을 행 방향으로 한다.
print(np.sort(array2d, axis=0))
print("\n")
# axis가 1일 때가 열(column)
# 오름차순을 열 방향으로 한다.
print(np.sort(array2d, axis=1))
원본 행렬이 정렬되었을 때, 기존 원본 행렬의 원소에 대한 인덱스를 필요로 할 때
np.argsort() 를 이용해서, 정렬 행렬 원본 행렬 인덱스를 ndarray로 반환합니다.
org_array = np.array ([3, 1, 9, 5])
sort_indices = np.argsort(org_array)
print(type(sort_indices))
print("정렬 시 인덱스 재배열 결과는 : ", sort_indices)
RDBMS : 관계형 데이터베이스 관리 시스템
하나의 person 이라고 하는 테이블 안에 이름, 나이, 동네 라고 하는 필드가 있고
그 안에 레코드라고 하는 독립적인 하나의 데이터들이 쌓입니다.
이름 | 나이 | 동네 |
(…) | (…) | (…) |
각각의 데이터인 레코드들은 필드의 속성을 공유합니다.
같은 속성의 데이터들이 만들어지는 것이 기본적인 속성입니다.
정렬된 인덱스의 반환
넘파이의 RDBMS 는 테이블 칼럼이나 판다스의 데이터프레임 칼럼같은 데이터를 가질 수 없습니다.
즉 배열은 [ 1, 2, 3, 4 ] 이렇게 되어있으므로 필드 가 없습니다. 데이터를 표현할 데이터는 없고 인덱스만 있습니다.
실제 값과 그 값이 뜻하는 메타 데이터를 각각 가져야 합니다.
별도의 필드명 데이터가 필요하다는 의미입니다.
이름 array 따로, 나이 array 따로, 동네 array 따로 마련해야 합니다.
name_array = np.array(["김주성", "유진성" , "이은혜", "정원홍"])
score_array = np.array([75, 85, 84, 98])
# 넘파이의 팬시 인덱싱으로 이름 출력
sort_indices_asc = np.argsort(score_array)
print("성적 오름차순 정렬 시 성적 인덱스: ", sort_indices_asc)
print("성적 오름차순 정렬 결과 이름으로 출력: ", name_array[sort_indices_asc])
선형대수 연산
넘파이는 다양한 선형대수 연산을 지원합니다.
그 중 가장 많이 사용되면서 기본적인 행렬 내적(내적은 두 텐서(벡터) 간의 관계를 나타내는 데이터입니다.)과 전치 행렬을 구하는 방법을 알아보겠습니다.
행렬 내적은 행렬 간의 곱입니다. (행과 열의 수가 같아야 성립이 됩니다.)
전치 행렬이란 행과 열의 위치를 교환한 원소로 구성한 행렬입니다.
A = np.array([[1,2,3],[4,5,6]])
B = np.array([[7,8],[9,10],[11,12]])
dot_product = np.dot(A,B)
print("내적 결과 : \n", dot_product)
A = np.array([[1,2],[3,4]])
transpose_mat = np.transpose(A)
print("A의 전치행렬 : \n", transpose_mat)
여기까지 Numpy의 기본 배열과 연산에 대해서 알아보았습니다.
다음에는 판다스를 짧게 리뷰할게요.