소개
이 실습에서는 NumPy 의 구조화된 배열 (structured arrays) 에 대해 배웁니다. 구조화된 배열은 데이터베이스 테이블이나 스프레드시트와 유사하게 이기종 데이터 (heterogeneous data) 를 다루는 강력한 기능입니다. 구조화된 배열의 각 요소는 행 (row) 으로 생각할 수 있으며, "필드 (fields)"라고 불리는 명명된 열 (column) 을 가집니다. 이를 통해 Python 내에서 직접 표 형식 데이터를 구성하고 조작하는 데 이상적입니다.
이 실습 전반에 걸쳐 WebIDE 에 제공된 structured_arrays.py 파일에서 Python 코드를 작성하고 실행하게 됩니다.
구조화된 배열 생성 및 접근
먼저 간단한 구조화된 배열을 만들어 보겠습니다. 구조화된 배열의 데이터 타입 (dtype) 은 튜플의 리스트로 정의됩니다. 각 튜플은 (이름, 데이터_타입) 형식으로 필드를 지정합니다. 이를 통해 문자열과 정수와 같이 서로 다른 데이터 타입을 동일한 배열에 저장할 수 있습니다.
왼쪽 패널의 파일 탐색기에서 structured_arrays.py 파일을 엽니다. 다음 코드를 추가하여 이름과 나이를 가진 사람들의 목록을 나타내는 구조화된 배열을 생성합니다.
## Create a structured array
data = np.array([('Alice', 25, 55.5), ('Bob', 30, 68.0)],
dtype=[('name', 'U10'), ('age', 'i4'), ('weight', 'f4')])
print("Original Array:")
print(data)
## Access a specific field by its name
names = data['name']
print("\nNames field:")
print(names)
코드 설명:
import numpy as np: NumPy 라이브러리를 가져옵니다.np.array([...], dtype=[...]): 배열을 생성합니다. 첫 번째 인자는 튜플의 리스트이며, 각 튜플('Alice', 25, 55.5)은 데이터의 한 행을 나타냅니다.dtype=[('name', 'U10'), ('age', 'i4'), ('weight', 'f4')]: 이것이 핵심 부분입니다. 세 개의 필드를 정의합니다:'name': 최대 길이가 10 자인 유니코드 문자열 (U10).'age': 4 바이트 (32 비트) 정수 (i4).'weight': 4 바이트 (32 비트) 부동소수점 수 (f4).
data['name']: 필드 이름 (열 이름) 을 인덱스로 사용하여 특정 필드의 모든 값에 접근할 수 있으며, 이는 새로운 NumPy 배열을 반환합니다.
이제 파일을 저장하고 터미널에서 실행하여 출력을 확인합니다.
python structured_arrays.py
전체 구조화된 배열과 이름만 포함된 배열을 보여주는 다음 출력을 볼 수 있습니다.
Original Array:
[('Alice', 25, 55.5) ('Bob', 30, 68. )]
Names field:
['Alice' 'Bob']
필드 수정 및 인덱싱
구조화된 배열은 변경 가능 (mutable) 하므로 값을 수정할 수 있습니다. 전체 필드를 한 번에 수정하거나, 인덱스로 특정 요소를 접근한 후 해당 필드를 수정할 수 있습니다. 또한 원본 필드의 일부를 포함하는 새 배열을 만들 수도 있습니다.
structured_arrays.py 스크립트 끝에 다음 코드를 추가합니다.
## Modify the 'age' field
data['age'] = [26, 31]
print("\nArray after modifying age:")
print(data)
## Access a single element (the first row)
first_person = data[0]
print("\nFirst person's data:")
print(first_person)
## Create a new array with a subset of fields
subset = data[['name', 'weight']]
print("\nSubset of array (name and weight):")
print(subset)
코드 설명:
data['age'] = [26, 31]: 이 코드는age필드에 새 값 리스트를 할당하여 전체 열을 업데이트합니다.data[0]: 배열의 첫 번째 요소 (행) 에 접근합니다. 결과는 해당 단일 행의 데이터를 보유하는 NumPy void scalar 입니다.data[['name', 'weight']]: 필드 이름 리스트를 전달하여 여러 열을 선택할 수 있으며, 이는 해당 필드만 포함하는 새 구조화된 배열을 생성합니다.
파일을 저장하고 터미널에서 다시 실행합니다.
python structured_arrays.py
이제 수정된 배열과 부분 집합을 보여주는 새 섹션이 출력에 포함됩니다.
... (previous output) ...
Array after modifying age:
[('Alice', 26, 55.5) ('Bob', 31, 68. )]
First person's data:
('Alice', 26, 55.5)
Subset of array (name and weight):
[('Alice', 55.5) ('Bob', 68. )]
레코드 배열을 사용한 속성 접근
이름으로 인덱싱하는 것 (data['name'] 등) 은 강력하지만 장황할 수 있습니다. NumPy 는 레코드 배열 (np.recarray) 이라고 하는 ndarray의 특별한 하위 클래스를 제공합니다. 레코드 배열을 사용하면 필드를 속성으로 접근할 수 있으며, 점 표기법 (record_array.name 등) 을 사용하여 코드를 더 깔끔하고 읽기 쉽게 만들 수 있습니다.
레코드 배열을 직접 생성하거나 기존 구조화된 배열을 변환할 수 있습니다. 두 가지 방법을 모두 살펴보겠습니다. structured_arrays.py 끝에 다음 코드를 추가합니다.
## Convert the structured array to a record array using view()
record_array = data.view(np.recarray)
print("\nType of the new view:")
print(type(record_array))
## Access fields using attribute (dot) notation
print("\nAccessing names via attribute:")
print(record_array.name)
print("\nAccessing ages via attribute:")
print(record_array.age)
코드 설명:
data.view(np.recarray):.view()메서드는 동일한 데이터를 보는 새 배열 객체를 생성합니다.np.recarray를 지정하면 구조화된 배열 데이터의 레코드 배열 뷰를 얻게 됩니다. 데이터는 복사되지 않습니다. 단지 데이터를 상호 작용하는 다른 방식일 뿐입니다.record_array.name: 이것이 레코드 배열의 핵심 기능입니다.name필드에 객체의 속성처럼 접근할 수 있습니다. 이는record_array['name']과 동일합니다.
파일을 저장하고 실행합니다.
python structured_arrays.py
출력에는 이제 새 배열 뷰의 타입이 표시되고 속성 접근이 시연됩니다.
... (previous output) ...
Type of the new view:
<class 'numpy.recarray'>
Accessing names via attribute:
['Alice' 'Bob']
Accessing ages via attribute:
[26 31]
요약
이 실습에서는 NumPy 에서 구조화된 배열을 사용하는 기본 사항을 배웠습니다. 명명된 필드와 여러 데이터 타입을 가진 구조화된 배열을 생성하는 것부터 시작했습니다. 그런 다음 사전 스타일 키 인덱싱을 사용하여 특정 필드 (열) 에 접근하고 값을 수정하는 연습을 했습니다. 마지막으로 필드를 속성으로 접근할 수 있는 편리한 대안인 레코드 배열을 탐색하고 .view() 메서드를 사용하여 표준 구조화된 배열과 레코드 배열 간에 변환하는 방법을 배웠습니다.
구조화된 배열은 Python 을 사용한 과학 컴퓨팅 및 데이터 분석에서 복잡한 테이블 형식 데이터를 처리하는 데 필수적인 도구입니다.



