개요
2022.11.11 - [Python] NumPy - 배열 1
2022.11.12 - [Python] NumPy - 배열 2 (인덱싱과 슬라이싱)
2022.11.13 - [Python] NumPy - 배열의 생성과 변형 1
에 이어 NumPy에 대해서 계속 정리한다.
배열의 크기 변형
reshape
reshape 함수로 배열 내 데이터는 유지하면서 형태를 변경할 수 있다.
a = np.arange(10)
a
a.reshape(2, 5)
# 실행 결과
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
사용하는 원소의 개수가 정해져 있기 때문에 매개변수로 전달하는 튜플 중 하나가 -1이면, 자동으로 차원을 계산하여 크기를 변경한다.
a = np.arange(10)
a = a.reshape(2, -1)
# 실행 결과
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
flatten / ravel
다차원 배열을 1차원으로 만들 때 사용한다.
a.flatten()
a.ravel()
# 실행 결과
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
💡
길이가 5인 1차원 배열, 5 X 1인 배열, 1 X 5인 배열 각각은 다른 배열이다.
np.newaxis
1차원만 증가시킨 배열을 구할 때 사용한다.
a = np.arange(5)
a.[:, np.newaxis]
# 실행 결과
array([[0],
[1],
[2],
[3],
[4]])
배열 연결
NumPy에서는 행의 수나 열의 수가 같은 두 개 이상의 배열을 연결(concatenate)하여 더 큰 배열을 만들 수 있다.
- hstack : 행의 수가 같은 두 개 이상의 배열을 옆으로 연결하여 열의 수가 더 많은 배열을 만든다. 연결할 배열은 리스트로 전달한다.
a1 = np.ones((2, 3))
a2 = np.zeros((2, 1))
a1
a2
np.hstack([a1, a2])
# 실행 결과
array([[1., 1., 1.],
[1., 1., 1.]])
array([[0.],
[0.]])
array([[1., 1., 1., 0.],
[1., 1., 1., 0.]])
- vstack : 열의 수가 같은 두 개 이상의 배열을 세로로 연결하여 행의 수가 더 많은 배열을 만든다. 연결할 배열은 리스트로 전달한다.
a1 = np.ones((1, 3))
a2 = np.zeros((2, 3))
a1
a2
np.vstack([a1, a2])
# 실행 결과
array([[1., 1., 1.]])
array([[0., 0., 0.],
[0., 0., 0.]])
array([[1., 1., 1.],
[0., 0., 0.],
[0., 0., 0.]])
- dstack : 행/열이 아닌 깊이(depth) 방향으로 배열을 합치며 가장 안쪽 원소의 차원이 증가한다. 즉, 가장 내부의 숫자 원소가 배열이 된다. 아래의 예제의 경우, 2개의 3 X 4 배열이 1개의 3 X 4 X 2 배열이 된다.
c1 = np.ones((3, 4))
c2 = np.zeros((3, 4))
c1
c2
np.dstack([c1, c2])
(np.dstack([c1, c2])).shape
# 실행 결과
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
array([[[1., 0.],
[1., 0.],
[1., 0.],
[1., 0.]],
[[1., 0.],
[1., 0.],
[1., 0.],
[1., 0.]],
[[1., 0.],
[1., 0.],
[1., 0.],
[1., 0.]]])
(3, 4, 2)
- stack : dstack의 기능을 확장한 것으로 사용자가 지정한 축(axis)으로 배열을 연결한다. 기본값은 axis = 0으로 맨 바깥에 차원이 추가된다.
c = np.stack([c1, c2])
c
c.shape
# 실행 결과
array([[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
(2, 3, 4)
- r_ : hstack과 비슷하게 배열을 좌우로 연결한다. 다만 함수임에도 불구하고 대괄호를 쓰는 특수 함수이다.
np.r_[np.array([1, 2, 3]), np.array([4, 5, 6])]
# 실행 결과
array([1, 2, 3, 4, 5, 6])
- c_ : 배열의 차원을 증가시킨 후 좌우로 연결한다. 1차원 배열은 2차원 배열이 된다.
np.c_[np.array([1, 2, 3]), np.array([4, 5, 6])]
# 실행 결과
array([[1, 4],
[2, 5],
[3, 6]])
- tile : 같은 배열을 반복하여 연결한다.
a = np.array([[0, 1, 2], [3, 4, 5]])
np.tile(a, 2)
# 실행 결과
array([[0, 1, 2, 0, 1, 2],
[3, 4, 5, 3, 4, 5]])
2차원 그리드 포인트 생성
변수가 2개인 2차원 함수의 그래프를 그리거나 표를 작성하기 위해서는 (x, y) 순서쌍을 생성하여 각 좌표에 대한 함숫값을 구해야 한다.
예로 들어 \(0 \le x \le 2\)이고 \(0 \le y \le 4 \)인 경우, 아래 순서쌍에 대한 함숫값을 계산해야 한다.
$$ (x, y) = (0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), … (2, 4) $$
이러한 순서쌍을 만들 때는 가로, 세로축의 점을 나타내는 두 벡터를 인수로 받아 그 조합을 출력하는 meshgrid 함수를 사용할 수 있다.
x = np.arange(3)
y = np.arange(5)
X, Y = np.meshgrid(x, y)
# X
array([[0, 1, 2],
[0, 1, 2],
[0, 1, 2],
[0, 1, 2],
[0, 1, 2]])
# Y
array([[0, 0, 0],
[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4]])
[list(zip(x, y)) for x, y in zip(X, Y)]
[[(0, 0), (1, 0), (2, 0)],
[(0, 1), (1, 1), (2, 1)],
[(0, 2), (1, 2), (2, 2)],
[(0, 3), (1, 3), (2, 3)],
[(0, 4), (1, 4), (2, 4)]]
참고 문서