1. 벡터
1-1. 벡터는 1행 또는 1열로 이루어진 1차원 배열
import numpy as np
vector_row=np.array([1,2,3]) # 1행으로 이루어진 행벡터
vector_column=np.array([[1], # 1열로 이루어진 열벡터
[2],
[3]])
1-2. asarray함수를 사용하여 배열을 만들수 있음
import numpy as np
new_row=np.asarray([1,2,3]) # np.array와 똑같이 1행으로 이루어진 행벡터 생성
np.asarray(넘파이 배열)은 새로운 배열 생성X
np.array(넘파이 배열)은 새로운 배열 생성
# array 사용
vector_row=np.array([1,2,3]) # 1행으로 이루어진 행벡터
new_row=np.array(vector_row) # array의 copy 매개변수는 배열을 복사할지 선택,
# 기본값은 True이므로 new_row에는 vector_row의 복사본 저장
new_row[0]=10 # new_row의 첫번째 값 변경
print('new_row:',new_row)
print('vector_row:',vector_row)
### 결과 ###
new_row: [10,2,3] # 복사본인 자기 자신에게만 영향을 주고
vector_row: [1,2,3] # 원래 배열에는 영향을 주지 않음
# asarray 사용
new_row=np.asarray(vector_row) # asarray는 새로운 배열을 생성하지 않고 원래의 배열 그 자체가 됨
new_row[0]=10 # new_row의 첫번째 값 변경
print('new_row:',new_row)
print('vector_row:',vector_row)
### 결과 ###
new_row: [10,2,3] # 자기 자신에게 영향을 주고
vector_row: [10,2,3] # 원래 배열에도 똑같이 영향을 줌
2. 행렬
2-1. 1개 이상의 행과 열로 이루어진 2차원 배열
import numpy as np
matrix=np.array([[1,2], # 3행 2열의 행렬
[1,2],
[1,2]])
matrix_object=np.mat([[1,2], # 3행 2열의 행렬, numpy의 행렬에 특화된 데이터 구조
[1,2],
[1,2]])
np.array()를 사용해 행렬 생성
np.mat가 행렬에 특화되어 있긴 하지만
-numpy의 표준 데이터 구조는 배열이고
-대부분의 넘파이 함수는 행렬 객체가 아닌 배열을 반환하므로
np.mat()보다는 np.array()를 사용
2-2. 희소행렬
데이터에서 0이 아닌 값이 매우 적을 때 이 데이터를 효율적으로 표현하는 방법
0이 아닌 값의 행과 열의 번호와 그 값만 저장됨
import numpy as np
from scipy import sparse
matrix=np.array([[0,0],
[0,1],
[3,0]])
matrix_sparse=sparse.csr_matrix(matrix)
print(matrix_sparse)
### 결과 ###
(1,1) 1 # 두번째 행, 두번째 열의 값 1
(2,0) 3 # 세번째 행, 첫번째 열의 값 3
위에서 사용한 것은 CSR(Compressed Sparse Row)이고
이외에도 CSC(Compressed Sparse Column), 리스트의 리스트, 키의 딕셔너리 등 여러 종류의 희소 행렬이 존재
가장 좋은 희소 행렬은 없고 각 희소 행렬 사이의 유의미한 차이를 통해 어떤 것을 적용하면 좋을 지 결정
-키의 딕셔너리(Dictionary of Keys, DOK): 행렬에서 0이 아닌 값의 (행번호, 열번호)를 키, 행렬값을 값으로 하는 딕셔너리
-리스트의 리스트(List of lists, LIL): 링크드 리스트 알고리즘 이용하여 추가와 삭제가 용이하지만 CSR과 CSC에 비해 메모리 낭비
-좌표 리스트(Coordinate list, COO): (행, 열, 값)의 튜플로 저장, 임의 엑세스 시간을 향상시키기 위해 행 인덱스→열 인덱스 순으로 정렬 가능, 점진적 행렬 구성에 유용
-CSR: 가로 순서대로 재정렬(행에 관해 정리 압축)
→데이터(A): 0이 아닌 행렬 값과 값의 (행 번호, 열 번호)가 저장
→열 인덱스 값(JA): 0행에서 값이 있는 열은 0, 3
1행에서 값이 있는 열은 2, 4
2행에서 값이 있는 열은 1
3행에서 값이 있는 열은 2, 4
→행 압축 정보(IA): (최초 시작행 번호, 시작행에 있는 데이터 개수, 두번째 행까지 데이터 누적 개수,..., 마지막행까지 데이터 누적 개수)
-CSC: 열에 관해 정렬한 것, CSR과 저장 알고리즘은 동일, LIL에 비해 저장 메모리 70% 이상 줄일 수 있지만 추가와 삭제가 용이하지 않음
# toarray
print(matrix_sparse.toarray())
### 결과 ###
[[0,0],
[0,1],
[3,0]] # 희소 행렬을 다시 밀집 배열로 변환
# todense
print(matrix_sparse.todense())
### 결과 ###
matrix([[0,0],
[0,1],
[3,0]]) # 희소 행렬을 np.matrix 객체로 변환
2-3. 벡터화 연산
배열의 여러 원소에 어떤 함수 적용하기
import numpy as np
matrix=np.array([[1,2,3],
[4,5,6],
[7,8,9]])
# 100을 더하는 함수
add_100=lambda i:i+100
# 함수를 np.vectorize(함수)를 통해 벡터화 시킴
vectorized_add_100=np.vectorize(add_100)
# 행렬에 벡터화된 함수를 적용시키면 행렬의 모든 원소에 함수 적용
vectorized_add_100(matrix)
### 결과 ###
array([[101,102,103],
[104,105,106],
[107,108,109]])
벡터화 연산은 기본적으로 for 루프를 구현한 것이므로 성능이 향상되지는 않음
2-4. 브로드캐스팅
넘파이 배열이 차원이 달라도 배열간 연산을 수행할 수 있음을 이용한 브로드캐스팅을 사용하면 더 간단하게 배열의 각 원소에 연산 적용 가능
# 1. 모든 원소에 100을 더함
matrix+100
### 결과 ###
array([[101,102,103],
[104,105,106],
[107,108,109]])
# 2. 행을 따라 더해짐
matrix+[100,100,10]
### 결과 ###
array([[101,102,13],
[104,105,16],
[107,108,19]])
# 3. 열을 따라 더해짐
matrix+[[100],[100],[10]]
### 결과 ###
array([[101,102,103],
[104,105,106],
[17,18,19]])
'Python > 기본문법' 카테고리의 다른 글
데이터 랭글링 (2) (0) | 2023.06.26 |
---|---|
데이터 랭글링 (1) (0) | 2023.06.23 |
데이터 적재 (0) | 2023.06.22 |
Numpy로 배열, 벡터, 행렬 이해하기 (3) (0) | 2022.10.20 |
Numpy로 배열, 벡터, 행렬 이해하기 (2) (0) | 2022.10.19 |