리스트는 요소들이 순서대로 저장된 자료형으로, 여러 개의 관련 값을 하나의 변수에 담을 수 있어 매우 유용합니다. 예를 들어 신발 10켤레의 이름을 하나의 변수에 저장하거나, 매장에서 구매한 물건 목록을 하나의 변수에 보관할 수 있습니다.
하지만 파이썬 기본 리스트만으로는 처리하기 어려운 고급 작업도 있습니다. 바로 이럴 때 NumPy의 배열(array) 자료형이 빛을 발합니다. NumPy 라이브러리를 활용하면 다차원 배열을 손쉽게 만들 수 있습니다.
이 글에서는 NumPy 배열이 무엇인지, 왜 유용한지, 그리고 코드에서 어떻게 다루는지 하나씩 살펴보겠습니다.
NumPy 배열이란?
NumPy 배열은 파이썬 라이브러리인 NumPy에서 사용되는 배열 객체입니다. NumPy는 'Numerical Python'의 약자로, 과학 및 수학 계산에 널리 쓰이는 패키지이며 데이터 분석과 고급 수학 연산을 돕는 다양한 도구를 함께 제공합니다.
외부 패키지 없이 순수 파이썬(vanilla Python)에서 제공하는 기본 배열도 강력하지만, 처리 속도가 느릴 수 있습니다. 반면 NumPy 배열은 일반적인 파이썬 배열보다 몇 배나 빠른 속도를 내도록 설계되었습니다.
이러한 성능 향상이 가능한 이유는 NumPy 배열이 값을 메모리의 연속된 공간에 저장하기 때문입니다. 덕분에 파이썬이 데이터에 더 쉽고 빠르게 접근하고 조작할 수 있습니다.
NumPy 배열 선언하는 방법
먼저 간단한 NumPy 배열을 만들어 보겠습니다. 이 튜토리얼에서는 문자열 값들을 배열에 저장해 볼 텐데요, 카페에서 판매하는 디저트 목록을 예로 들겠습니다. 우선 NumPy 라이브러리를 임포트합니다:
import numpy as np
이 코드는 numpy를 임포트하고 라이브러리에 np라는 별칭을 붙입니다. 따라서 이후에는 배열을 다룰 때마다 np만 호출하면 됩니다.
다음으로 array 인터페이스를 사용해 배열을 선언합니다:
treats = np.array(["Blueberry Muffin", "Cinnamon Bun", "Jammy Shortbread"])
print(treats)
배열에는 세 개의 문자열 값이 들어 있습니다. 일반 파이썬 리스트처럼 모든 항목을 대괄호로 감싸고, NumPy 배열을 선언하기 위해 np에 포함된 array 메서드를 사용했습니다. 이렇게 하면 NumPy의 기본 배열 타입인 ndarray 객체가 생성됩니다.
위 코드를 실행하면 원본 배열이 NumPy 배열로 변환된 결과가 출력됩니다:
['Blueberry Muffin' 'Cinnamon Bun' 'Jammy Shortbread']
이제 우리가 자유롭게 다룰 수 있는 배열이 준비되었습니다!
NumPy 배열의 차원(Dimension)
여기서 말하는 차원은 영화에 나오는 세계 같은 것이 아니라, 배열 안의 깊이(depth) 단계를 의미합니다. 즉, 차원이라는 용어는 중첩 배열(nested array), 즉 배열 안에 또 다른 배열이 포함된 구조를 가리킵니다.
배열은 원하는 만큼 많은 차원을 가질 수 있지만, 실무에서 주로 다루는 배열은 대부분 1차원(1-D), 2차원(2-D), 3차원(3-D)입니다. 여기서 'D'는 dimension(차원)을 뜻합니다.
NumPy 1차원(1-D) 배열
앞선 첫 번째 예제에서 만든 것은 1차원 배열입니다. 1차원 배열은 0차원 배열(즉, 개별 항목)들을 요소로 가지는 배열입니다. 우리가 다루는 대부분의 배열은 이 1차원 형태입니다.
카페 디저트의 가격을 저장하는 배열을 만들어 보겠습니다:
import numpy as np
prices = np.array([1.95, 2.00, 2.05])
print(prices)
코드를 실행하면 값들이 1차원 배열에 저장된 결과가 출력됩니다: [1.95 2. 2.05]
1차원 배열의 요소에 접근하는 방법은 파이썬 리스트와 동일합니다. 두 번째 항목을 가져와 볼까요?
print(prices[1])
이 코드는 인덱스 1에 해당하는 항목, 즉 2를 반환합니다.
NumPy 2차원(2-D) 배열
모든 배열이 1차원인 것은 아닙니다. 예를 들어 두 개의 배열을 하나의 배열에 담고 싶다고 가정해 봅시다. 하나는 카페에서 판매하는 디저트 목록, 다른 하나는 커피 목록이며, 이 둘을 합쳐 menu_items(메뉴 항목) 배열로 만드는 것입니다.
NumPy로 이 배열을 만들어 보겠습니다:
import numpy as np
menu_items = np.array([
["Blueberry Muffin", "Cinnamon Bun", "Jammy Shortbread"],
["Cappuccino", "Espresso", "Mocha"]
])
print(menu_items)
실행 결과는 다음과 같습니다:
[['Blueberry Muffin' 'Cinnamon Bun' 'Jammy Shortbread']
['Cappuccino' 'Espresso' 'Mocha']]
방금 만든 배열은 2차원입니다. 배열 안의 첫 번째 배열은 디저트 목록을, 두 번째 배열은 커피 목록을 담고 있으며, 두 배열이 하나의 대괄호로 묶여 있는 것을 확인할 수 있습니다.
2차원 배열에서 요소를 꺼내는 방법은 파이썬과 조금 다릅니다. 2차원 배열의 요소에 접근하려면 가져오려는 값의 인덱스 번호들을 쉼표로 구분해서 지정해야 합니다.
다음 코드를 살펴보세요:
print(menu_items[0, 2])
실행 결과는 'Jammy Shortbread'입니다. 인덱스 0번 배열 안에서 인덱스 2에 해당하는 항목을 가져온 것으로, 디저트 배열의 마지막 항목이 조회됩니다.
NumPy 3차원(3-D) 배열
이번에는 차원을 하나 더 추가해 보겠습니다! NumPy 배열은 2차원 배열들을 포함하는 3차원 배열도 가질 수 있습니다.
예를 들어 다음 값들을 저장한다고 가정해 봅시다:
- 달콤한 음식과 달지 않은 음식 (각각 별도의 배열로 묶음)
- 카페인 음료와 카페인 없는 음료 (각각 별도의 배열로 묶음)
이 모든 값들은 하나의 배열 안에 저장됩니다. 각 차원의 구성은 다음과 같습니다:
- 1차원: 전체 메뉴 항목
- 2차원: 달콤한 음식 및 달지 않은 음식, 카페인 음료 및 카페인 없는 음료
- 3차원: 달콤한 음식, 달지 않은 음식, 카페인 음료, 카페인 없는 음료
NumPy로 이 배열을 만들어 보겠습니다. 아래 코드를 파이썬 파일에 붙여 넣으세요:
import numpy as np
menu_items = np.array([
[
["Blueberry Muffin", "Cinnamon Bun", "Jammy Shortbread"],
["Smoked Bacon Roll", "Tuna Melt Panini", "Cheese and Tomato Toastie"]
],
[
["Cappuccino", "Espresso", "Mocha"],
["Apple Juice", "Water", "Orange Juice"]
]
])
print(menu_items)
실행 결과:
[[['Blueberry Muffin' 'Cinnamon Bun' 'Jammy Shortbread']
['Smoked Bacon Roll' 'Tuna Melt Panini' 'Cheese and Tomato Toastie']]
[['Cappuccino' 'Espresso' 'Mocha']
['Apple Juice' 'Water' 'Orange Juice']]]
앞서 설명한 모든 정보를 담은 3차원 배열이 완성되었습니다. 이 배열은 카페 메뉴 전체를 한눈에 볼 수 있는 종합 목록입니다.
3차원 배열에서 항목에 접근하는 방법도 2차원 배열과 비슷합니다. 다만 세 번째 인덱스까지 지정해야 한다는 점이 다릅니다. 배열에서 'Mocha'를 꺼내 보겠습니다:
print(menu_items[1, 0, 2])
실행 결과는 'Mocha'입니다.
첫 번째 인덱스 1은 접근하려는 1차원(음료 배열)을, 두 번째 인덱스 0은 2차원(카페인 음료 배열)을, 세 번째 인덱스 2는 3차원(Mocha 항목)을 가리킵니다.
배열의 차원 개수 확인하기
차원이 늘어날수록 배열의 구조는 점점 복잡해 보일 수 있습니다. 사실 우리는 아직 3차원을 넘는 배열조차 살펴보지 않았습니다! 다행히 배열이 몇 차원인지 손쉽게 확인할 수 있는 방법이 있습니다.
아래 코드를 파이썬 파일에 붙여 넣고 실행해 보세요:
import numpy as np
menu_items = np.array([
["Blueberry Muffin", "Cinnamon Bun", "Jammy Shortbread"],
["Cappuccino", "Espresso", "Mocha"]
])
print(menu_items.ndim)
코드를 실행하면 '2'가 출력됩니다. 이는 배열이 2차원이라는 뜻이며, 위 배열 구조를 분석해 보면 실제로 그렇다는 것을 알 수 있습니다.
마무리
NumPy 배열은 유사한 값들을 저장하는 유연한 방법으로, 전통적인 파이썬 배열보다 빠르고 효율적입니다. 또한 NumPy를 사용하면 다차원 배열도 손쉽게 다룰 수 있는데, 이는 순수 파이썬만으로 처리하기 어려운 작업입니다.
이제 여러분도 전문가처럼 NumPy 배열을 활용할 준비가 되었습니다!