파이썬/라이브러리(API)

파이썬 Numpy 수치해석용 라이브러리

코데방 2024. 3. 5.
728x90

Numpy 사용 준비

 

파이썬의 넘파이(numpy) 라이브러리는 다차원의 배열 자료구조, 벡터와 행렬을 사용하는 선형대수 계산에 주로 사용되는 파이썬의 대표적인 데이터 분석 및 머신러닝 라이브러리 중 하나입니다. 

 

혹시 numpy import가 되지 않고 모듈을 찾을 수 없다는 "ModuleNotFoundError"가 난다면 설치가 되어있지 않다는 말입니다. 

 

아나콘다를 설치해 VS Code 등 개발툴과 연동했다면 무리 없이 사용이 가능합니다. 그렇지 않다면 터미널에서 "pip install numpy"를 입력해 설치 후 사용하면 됩니다. 

 

보통 numpy는 np로 명명해 사용합니다.

import numpy as np

 

 

 

 

Numpy 행렬

 

행렬은 다중 리스트 구조를 의미합니다. 넘파이는 행렬 구조의 데이터를 아주 수월하게 다룰 수 있도록 해줍니다.

 

먼저 일반 리스트를 넘파이 클래스의 객체로 변환해줍니다. 이를 행렬 변환이라고 합니다. 

# 일반 리스트 -> numpy 행렬로 변환
numpy_array = np.array(lst)

# 타입 확인
print(type(numpy_array))

# 행렬 구조 확인
print(numpy_array.shape)



 

 

위 코드의 결과값을 확인해보면 오브젝트 클래스는 'numpy.ndarray'이며 10개로 이루어진 1차원 행렬이라는 것을 알 수 있습니다. 

 

 

만약 2개의 리스트로 이루어진 리스트를 행렬변환시킨다면 아래와 같은 결과가 나옵니다. "2행 10열"의 행렬 구조라는 의미입니다.

# 일반 리스트
lst = [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]]

# 일반 리스트 -> numpy 행렬로 변환
numpy_array = np.array(lst)

# 타입 확인
print(type(numpy_array))

# 행렬 구조 확인
print(numpy_array.shape)

 

 

 

 

 

numpy 객체로 변환된 행렬은 복잡한 반복문 없이도 데이터를 병렬 연산하여 일괄적으로 다루기 쉽습니다. 위 행렬에서 일괄적으로 숫자를 더한다면 아래와 같이 사용하면 됩니다.

 

참고로 넘파이의 행렬에서는 리슽크와 달리 콤마로 구분되어 출력되지 않습니다. 

# 행렬의 모든 값에 3을 더해줌
numpy_array += 3
print(numpy_array)

 

 

 

 

위와 같은 형태를 2차원 행렬이라고 합니다. 리스트 안에 리스트가 있는 구조라고 보면 됩니다.

 

그렇다면 3차원 행렬은 리스트 안에 리스트 안에 리스트가 있는 구조가 됩니다. 3차원 행렬까지는 그림으로 그릴만하지만 그 이상 차수는 머릿속으로 그리기조차 쉽지가 않습니다. 

 

 

 

 

 

따라서 행렬의 차수, 즉 차원을 확인하기 위해서는 아래와 같이 "ndim" 메소드를 사용해주면 됩니다.

# 차원 확인
# 결과 : 2
print(numpy_array.ndim)

 

 

 

 

 

데이터를 넘파이 행렬로 바꿔줄 때는 타입 변환에 유의해야합니다. 문자열과 숫자가 섞여있다면 모두가 문자열로, 정수와 실수가 섞여있다면 모두 실수로 변환됩니다. 

 

타입을 확인하기 위해서는 "dtype" 메소드를, 실수와 정수 타입을 바꿔주려면 "astype" 메소드를 사용해주면 됩니다.

 

추가로 실수를 int64 / int32 타입의 정수로 변환할 경우 소수점 이하는 모두 날아가게 된다는 점에 주의해야합니다. 

# 일반 리스트
lst = [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]]

# 일반 리스트 -> numpy 행렬로 변환
array = np.array(lst)

# 정수형 행렬을 실수형으로 변환
array_float = array.astype("float64")
print(array_float, array_float.dtype)

# 다시 실수형을 정수형으로 변환
array_int = array_float.astype("int64")
print(array_int, array_int.dtype)

 

 

 

 

"arange()" 메소드를 사용해 파이썬이 for문에서처럼 범위로 행렬을 생성할 수도 있습니다. 

array = np.arange(1, 10)
print(array)

 

 

 

 

베이스가 되는 행렬의 구조를 먼저 잡아주기 위해 "zeros()" 메소드를 통해 0으로 채워진 행렬을 쉽게 만들 수도 있습니다. 

# 3열 3행의 행렬이 3개 들어간 3차원 구조 행렬
array = np.zeros((4, 3, 3), dtype="int64")
print(array)

 

 

 

 

 

마찬가지로  "ones()" 메소드를 통해 1로 채워진 행렬을 만들 수도 있습니다.

 

물론 위의 "zeros()" 메소드로 만들어진 array에 1을 더해줘도 같은 결과를 얻을 수 있습니다. 

# 3열 3행의 행렬이 3개 들어간 3차원 구조 행렬
array = np.ones((4, 3, 3), dtype="int64")
print(array)

 

 

 

 

"reshape()" 메소드를 통해 차원 계수를 바꿔줄 수도 있습니다.

 

아래와 같이 1차원 행렬을 2차원, 3차원 이상으로 바꿀 수 있습니다. 

# 0~9까지 1차원 행렬
array = np.arange(10)

# 2차원 행렬(2열 5행)으로 변환
array2 = array.reshape(2,5)
print(array2)

 

 

 

다만 주의할 점은 나눠지는 숫자가 맞아 떨어지지 않으면 에러가 난다는 점입니다. 

# 3열 3행으로 변환
array3 = array.reshape(3,3)
print(array3)

 

 

 

numpy 행렬의 인덱싱이나 슬라이스는 리스트와 대부분 유사합니다. 

# 0~9까지 1차원 행렬
array = np.arange(10)

print(array[2:5])
array[9] = 1000
print(array)

 

 

 

 

다차원 행렬에서는 리스트와 같이 [x][y] 구조도 가능하지만 리스트와 달리 [x, y] 형태로 사용해줘도 가능합니다.

# 2차원 리스트
lst = [[1,2,3],[4,5,6]]

# 2차원 행렬 (리스트와 같은 값)
array = np.arange(1,7).reshape(2,3)

print(lst[0][1])
# print(lst[0, 1]) 에러남
print(array[0][1])
print(array[0, 1])

 

 

 

 

다만 3차원 이상의 행렬로 넘어갈 경우 아래와 같이 사용해줘야합니다.

 

"2행 2열"의 2차원 행렬이 3개 있는 3차원 행렬이라고 할 경우 인덱싱은 아래와 같이 할 수 있습니다. 

# 2행 2열 2차원 행렬이 3개 있는 3차원 행렬 생성
array = np.arange(12).reshape(3,2,2)
print(array)

 

 

 

먼저 첫 번째 2차원 행렬만 가져오고 싶다면 아래와 같이 인덱싱하면 됩니다.

print(array[0])

 

 

 

아래와 같이 복잡한 인덱싱도 가능합니다. 0번째와 2번째의 2차원 행렬에서 1번째 열을 가지고 오라는 의미입니다. 역시 2개의 인덱스를 사용한 셈이기 때문에 2차원 행렬로 나타납니다.

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

 

 

 

 

 

3개의 인덱스를 사용한다면 하나의 숫자만 가져올 수 있습니다.

print(array[0,1,1])

 

 

 

인덱싱에 조건을 부여하는 불리언 인덱싱도 가능합니다.

 

# 5보다 큰 값만 가지고 오기
print(array[array > 5])

 

 

 

 

정렬 또한 가능합니다.

 

np.sort(array) 메소드는 원본은 건드리지 않고 정렬된 새로운 행렬을 반환하고, array.sort() 함수는 원본의 배열 자체를 바꿔주는 점에 주의하면 됩니다. 

# 데이터 정렬
array2 = np.sort(array)
print(array2) 
print(array) # 원본은 바뀌지 않음
array.sort()
print(array) # 원본이 바뀌는 sort() 메소드

 

 

 

 

정렬함수를 사용할 때 "axis" 옵션값을 추가하면 행방향 또는 열방향으로 정렬할지를 결정할 수 있습니다.

 

기본인 "axis=1" 에서는 열방향, 즉 가로방향으로 정렬이 되고, "axis=0" 값을 주면 행방향, 즉 세로방향으로 정렬이 됩니다.

# 2행 2열 2차원 행렬이 3개 있는 3차원 행렬 생성
lst = [[141,12,0],[122,1,22]]
array = np.array(lst)

# 데이터 정렬
array2 = np.sort(array, axis = 0) # 행방향 정렬
print(array2) 
print(array) # 원본은 바뀌지 않음
array.sort()
print(array) # 원본이 바뀌는 sort() 메소드

 

 

 

 

"argsort()" 메소드를 사용하면 행렬 자체를 정렬하지 않고 정렬된 순서를 가진 인덱스만 얻을 수 있습니다. 

# 2행 2열 2차원 행렬이 3개 있는 3차원 행렬 생성
lst = [141,12,0]
array = np.array(lst)

# 작은 순서의 인덱스를 반환
print(array.argsort())

 

 

 

 

"dot()" 메소드를 이용해 행렬끼리 곱셈 또한 쉽게 가능합니다. 행렬 내적이라고 합니다.

array1 = np.array([[1, 2, 3], [4, 5, 6]])
array2 = np.array([[7, 8], [9, 10], [11, 12]])
print(np.dot(array1, array2))

 

 

 

 

"transpose()" 메소드를 통해 행과 열을 바꾼 전치 행렬을 쉽게 수행할 수도 있습니다.

array = np.array([[1, 2, 3], [4, 5, 6]])
print(array)
print(np.transpose(array)) # 전치 행렬

 

728x90

댓글

💲 추천 글