NumPy 배열 생성 기본 기법

NumPyBeginner
지금 연습하기

소개

사전 준비 사항

이 과정을 시작하기 전에 기본적인 Python 프로그래밍 기술이 있어야 합니다. 아직 Python 을 배우지 않았다면, 저희의 Python 학습 경로부터 시작할 수 있습니다.

NumPy 배열 생성의 기본 기술에 대한 실습에 오신 것을 환영합니다. 코딩을 시작하기 전에 NumPy 가 무엇인지, 그리고 과학 컴퓨팅에 왜 필수적인지 이해해 봅시다.

NumPy 란 무엇인가?

NumPy (Numerical Python 의 약자) 는 Python 에서 과학 컴퓨팅을 위한 핵심 라이브러리입니다. 대규모 수치 데이터 배열 및 행렬 작업을 위한 강력한 데이터 구조와 함수를 제공합니다.

Python 리스트 대신 NumPy 를 사용하는 이유?

Python 의 내장 리스트는 유연하고 사용하기 쉽지만, 수치 데이터를 다룰 때는 다음과 같은 한계가 있습니다.

  • 성능: NumPy 배열은 수학 연산에 훨씬 빠릅니다.
  • 메모리 효율성: NumPy 는 동일한 양의 데이터를 저장하는 데 더 적은 메모리를 사용합니다.
  • 편의성: NumPy 는 수백 가지의 내장 수학 함수를 제공합니다.
  • 기능: NumPy 는 행렬 곱셈, 푸리에 변환 등 고급 연산을 지원합니다.

이 실습에서는 NumPy 배열을 생성하는 가장 일반적인 방법들을 배우게 됩니다. Python 시퀀스를 변환하고, 내장 NumPy 함수를 사용하고, 기존 배열을 조작하고, 파일에서 데이터를 로드하는 연습을 위해 Python 스크립트를 작성하고 실행할 것입니다. 모든 코딩은 WebIDE 내에서 이루어집니다.

Python 시퀀스로부터 배열 생성하기

NumPy 배열을 생성하는 가장 기본적인 방법은 리스트나 튜플과 같은 Python 시퀀스를 변환하는 것입니다. numpy.array() 함수는 시퀀스를 인자로 받아 새로운 NumPy 배열을 반환합니다.

NumPy 배열 이해하기

배열을 생성하기 전에 NumPy 배열이 특별한 이유를 이해해 봅시다.

배열 차원

  • 1D 배열 (벡터): [1, 2, 3, 4]와 같은 단순한 숫자 리스트
  • 2D 배열 (행렬): 스프레드시트처럼 행과 열이 있는 숫자 테이블
  • 3D 배열 (텐서): 이미지나 3D 데이터에 유용한 숫자 큐브

Array Dimensions

Python 리스트와의 주요 차이점

  • 동일한 타입 (Homogeneous): 모든 요소는 동일한 데이터 타입이어야 합니다 (일반적으로 숫자).
  • 고정 크기 (Fixed size): 생성 후에는 크기를 변경할 수 없습니다.
  • 효율성 (Efficient): 수학 연산에 훨씬 빠릅니다.
  • 풍부한 기능 (Rich functionality): 벡터화된 연산 (전체 배열에 대한 연산을 한 번에 수행) 을 지원합니다.

NumPy 가져오기

Python 에서는 표준 별칭 np를 사용하여 NumPy 를 가져옵니다.

import numpy as np

np 별칭은 과학 계산 Python 커뮤니티에서 널리 채택된 관례입니다.

이제 몇 가지 배열을 만들어 보겠습니다. 왼쪽 파일 탐색기에서 array_from_sequence.py 파일을 엽니다. 다음 코드를 추가하십시오. 이 코드는 NumPy 라이브러리를 가져오고 Python 리스트로부터 1 차원 (1D), 2 차원 (2D), 3 차원 (3D) 배열을 생성합니다.

Python code to create NumPy arrays

import numpy as np

## 리스트로부터 1D 배열 생성
a1D = np.array([1, 2, 3, 4])
print("1D Array:")
print(a1D)

## 리스트의 리스트로부터 2D 배열 생성
a2D = np.array([[1, 2], [3, 4]])
print("\n2D Array:")
print(a2D)

## 중첩된 리스트로부터 3D 배열 생성
a3D = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print("\n3D Array:")
print(a3D)

제안: 위의 코드를 코드 편집기에 복사한 다음 각 코드 줄을 주의 깊게 읽어 기능을 이해하십시오. 추가 설명이 필요한 경우 "코드 설명" 버튼 👆을 클릭할 수 있습니다. Labby 와 상호 작용하여 맞춤형 도움을 받을 수 있습니다.

코드를 추가한 후 파일을 저장합니다. 이제 터미널에서 스크립트를 실행하여 출력을 확인합니다.

python array_from_sequence.py

생성한 배열을 표시하는 다음과 같은 출력을 볼 수 있습니다.

1D Array:
[1 2 3 4]

2D Array:
[[1 2]
 [3 4]]

3D Array:
[[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]]

데이터 타입 (dtype) 이해하기

NumPy 배열은 dtype 매개변수로 지정되는 모든 요소에 대해 고정된 데이터 타입을 가집니다. 이는 각 요소가 다른 타입을 가질 수 있는 Python 리스트와 다릅니다.

데이터 타입이 중요한 이유

  • 메모리 효율성: 다른 타입은 다른 양의 메모리를 사용합니다.
  • 성능: 연산은 특정 데이터 타입에 최적화되어 있습니다.
  • 정밀도: 숫자가 저장되고 계산되는 방식을 제어합니다.

일반적인 데이터 타입

  • int32 / int64: 정수 (32 또는 64 비트)
  • float32 / float64: 소수점 이하 숫자 (32 또는 64 비트)
  • complex: 복소수
  • bool: True/False 값

np.array([1, 2], dtype=complex)와 같이 dtype 매개변수를 사용하여 배열을 생성할 때 데이터 타입을 지정할 수 있습니다. dtype 을 지정하지 않으면 NumPy 는 입력 데이터에 따라 적절한 타입을 자동으로 선택합니다.

내장 배열 생성 함수 사용하기

NumPy 는 Python 시퀀스를 필요로 하지 않고 처음부터 배열을 생성하는 여러 내장 함수를 제공합니다. 이러한 함수는 특정 사용 사례에 최적화되어 있으며 리스트에서 수동으로 배열을 생성하는 것보다 훨씬 빠릅니다.

이러한 함수를 사용하는 이유?

np.array([0, 0, 0, 0, 0])를 작성하는 대신 np.zeros(5)를 사용할 수 있습니다. 이러한 함수는 다음과 같습니다.

  • 더 빠름: 내부적으로 최적화된 C 코드 사용
  • 더 읽기 쉬움: 함수 이름에서 의도가 명확합니다.
  • 메모리 효율성: 직접적인 메모리 할당
  • 편리함: 각 요소를 수동으로 지정할 필요가 없습니다.

intrinsic_creation.py 파일을 열고 다음 코드를 추가합니다. 이 스크립트는 몇 가지 일반적인 생성 함수를 시연합니다.

import numpy as np

## 요소 범위로 배열 생성
## np.arange(start, stop, step) - Python 의 range() 와 유사
## 사용 사례: 루프를 위한 시퀀스 생성, 인덱스 생성
arr_range = np.arange(0, 10, 2)  ## [0, 2, 4, 6, 8]
print("Array from arange:")
print(arr_range)

## 두 점 사이의 특정 개수 요소로 배열 생성
## np.linspace(start, stop, num_elements) - 균일하게 간격이 떨어진 점
## 사용 사례: 플로팅을 위한 점 생성, 데이터 샘플링
arr_linspace = np.linspace(0, 10, 5)  ## 0 부터 10 까지 5 개의 점
print("\nArray from linspace:")
print(arr_linspace)

## 0 으로 채워진 배열 생성
## np.zeros((rows, columns)) - 계산을 위한 배열 초기화
## 사용 사례: 계산된 값으로 채우기 전에 배열 사전 할당
arr_zeros = np.zeros((2, 3))  ## 0 으로 채워진 2x3 배열
print("\nArray of zeros:")
print(arr_zeros)

## 1 로 채워진 배열 생성
## np.ones((rows, columns)) - 1 로 초기화
## 사용 사례: 마스크, 스케일링 팩터 또는 알고리즘 시작점 생성
arr_ones = np.ones((3, 2))  ## 1 로 채워진 3x2 배열
print("\nArray of ones:")
print(arr_ones)

## 항등 행렬 생성
## np.eye(size) - 대각선에 1, 나머지는 0 인 정사각형 행렬
## 사용 사례: 선형 대수, 변환 재설정, 행렬 곱셈
identity_matrix = np.eye(3)  ## 3x3 항등 행렬
print("\nIdentity matrix:")
print(identity_matrix)

파일을 저장하고 터미널에서 실행합니다.

python intrinsic_creation.py

출력에는 이러한 함수로 생성된 다양한 배열이 표시됩니다.

Array from arange:
[0 2 4 6 8]

Array from linspace:
[ 0.   2.5  5.   7.5 10. ]

Array of zeros:
[[0. 0. 0.]
 [0. 0. 0.]]

Array of ones:
[[1. 1.]
 [1. 1.]
 [1. 1.]]

Identity matrix:
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]

기존 배열 조작하기

기존 배열을 수정, 결합 또는 분할하여 새 배열을 만들 수도 있습니다. 이 섹션에서는 뷰 (view) 대 복사본 (copy) 및 **배열 연결 (concatenation)**이라는 두 가지 중요한 개념을 다룹니다.

뷰 대 복사본: 메모리 공유 이해하기

이것은 초보자들이 종종 혼란스러워하는 NumPy 의 가장 중요한 개념 중 하나입니다.

뷰 (View) 란 무엇인가?

는 메모리 내의 동일한 데이터를 보는 다른 방식입니다. 뷰를 생성할 때 (슬라이싱을 통해), 새로운 배열을 만드는 것이 아니라 기존 데이터에 대한 새로운 참조를 만드는 것입니다.

복사본 (Copy) 이란 무엇인가?

복사본은 메모리에 자체 데이터로 완전히 새로운 배열을 만듭니다. 복사본을 수정해도 원본 배열에 영향을 미치지 않으며, 그 반대도 마찬가지입니다.

이것이 중요한 이유

  • 뷰는 메모리 효율적입니다: 데이터를 복제하지 않습니다.
  • 뷰는 빠릅니다: 복사 오버헤드가 없습니다.
  • 하지만 뷰는 예상치 못한 부작용을 일으킬 수 있습니다: 뷰를 수정하면 원본 데이터가 변경됩니다.
  • 복사본은 더 안전합니다: 변경 사항은 격리되지만 더 많은 메모리를 사용합니다.

또한 여러 배열을 하나의 더 큰 배열로 결합하는 방법도 살펴보겠습니다.

array_manipulation.py 파일을 열고 다음 코드를 추가합니다.

import numpy as np

## --- 파트 1: 뷰 대 복사본 ---
a = np.arange(1, 5)
print("Original array 'a':", a)

## 처음 두 요소의 뷰 생성
b = a[:2]
b[0] = 99 ## 뷰 수정
print("Modified view 'b':", b)
print("Array 'a' after modifying the view:", a) ## 'a'도 변경됨

## 복사본 생성
c = a[:2].copy()
c[0] = 0 ## 복사본 수정
print("\nModified copy 'c':", c)
print("Array 'a' after modifying the copy:", a) ## 'a'는 변경되지 않음

## --- 파트 2: 배열 결합 ---
A = np.ones((2, 2))
B = np.eye(2) * 2
C = np.zeros((2, 2))
D = np.diag((-3, -4))

## 배열을 블록 행렬로 결합
block_matrix = np.block([
    [A, B],
    [C, D]
])
print("\nBlock matrix:")
print(block_matrix)

파일을 저장하고 터미널에서 실행합니다.

python array_manipulation.py

출력은 뷰를 수정하는 것이 원본 배열에 영향을 미치는 방식과 복사본을 수정하는 것이 그렇지 않은 방식을 보여줍니다. 또한 네 개의 작은 배열을 하나의 블록 행렬로 결합한 결과도 보여줍니다.

Original array 'a': [1 2 3 4]
Modified view 'b': [99  2]
Array 'a' after modifying the view: [99  2  3  4]

Modified copy 'c': [0 2]
Array 'a' after modifying the copy: [99  2  3  4]

Block matrix:
[[ 1.  1.  2.  0.]
 [ 1.  1.  0.  2.]
 [ 0.  0. -3.  0.]
 [ 0.  0.  0. -4.]]

파일에서 배열 읽기

데이터 분석에서 일반적인 작업은 파일을 NumPy 배열로 로드하는 것입니다. NumPy 는 대규모 데이터셋을 효율적으로 읽고 적절한 숫자 형식으로 자동 변환할 수 있기 때문에 이 작업에 탁월합니다.

파일 I/O 에 NumPy 를 사용하는 이유

  • 속도: Python 으로 줄 단위로 읽는 것보다 훨씬 빠릅니다.
  • 타입 추론: 적절한 데이터 타입을 자동으로 감지합니다.
  • 메모리 효율성: 데이터를 최적화된 배열로 직접 로드합니다.
  • 편의성: 복잡한 파싱 대신 단일 함수 호출로 처리합니다.

일반적인 파일 형식

  • CSV 파일: 쉼표로 구분된 값 (가장 일반적)
  • TSV 파일: 탭으로 구분된 값
  • 텍스트 파일: 공백 또는 사용자 지정 구분 기호로 구분
  • 이진 파일: 매우 큰 데이터셋용 (고급)

CSV(Comma-Separated Values) 와 같은 간단한 텍스트 파일의 경우 NumPy 는 np.loadtxt() 함수를 제공합니다.

이 실습의 설정 스크립트는 이미 프로젝트 디렉토리에 data.csv라는 파일을 생성했습니다. 내용은 다음과 같습니다.

col1,col2,col3
1.0,2.5,3.2
4.5,5.0,6.8
7.3,8.1,9.9

이제 read_from_file.py 파일을 열고 이 데이터를 읽기 위해 다음 코드를 추가합니다.

np.loadtxt 매개변수 이해하기

np.loadtxt() 함수에는 몇 가지 중요한 매개변수가 있습니다.

  • delimiter=',': 열이 구분되는 방식을 지정합니다 (CSV 의 경우 쉼표).
  • skiprows=1: 첫 번째 행 (일반적으로 헤더) 을 건너뜁니다.
  • dtype: 선택 사항 - 데이터 타입을 지정합니다 (제공되지 않으면 자동 감지).
  • usecols: 선택 사항 - 읽을 열을 지정합니다.
  • comments: 선택 사항 - 무시할 줄을 지정하는 주석 문자입니다.

열이 쉼표로 구분됨을 지정하기 위해 delimiter=','를 사용하고 헤더 행을 무시하기 위해 skiprows=1을 사용합니다.

import numpy as np

## CSV 파일에서 데이터 로드
try:
    ## 상대 경로는 유효성 검사에 실패하므로 실습에서는 절대 경로를 사용하십시오.
    data = np.loadtxt('/home/labex/project/data.csv', delimiter=',', skiprows=1)
    print("Data loaded from data.csv:")
    print(data)
except IOError:
    print("Error: data.csv not found.")

파일을 저장하고 터미널에서 실행합니다.

python read_from_file.py

스크립트는 data.csv에서 숫자 데이터를 읽어 NumPy 배열로 출력합니다.

Data loaded from data.csv:
[[1.  2.5 3.2]
 [4.5 5.  6.8]
 [7.3 8.1 9.9]]

이 방법은 구조화된 숫자 데이터를 배열로 로드하여 추가 처리를 하는 데 매우 효율적입니다.

요약

이 랩에서는 NumPy 배열을 생성하는 기본적인 기술을 배웠습니다. Python 리스트에서 배열을 생성하고, np.arangenp.zeros와 같은 내장 함수를 사용하고, 뷰, 복사본 및 결합을 통해 기존 배열을 조작하고, np.loadtxt를 사용하여 텍스트 파일에서 데이터를 로드하는 연습을 했습니다.

이러한 기술은 Python 으로 수행할 거의 모든 수치 및 과학 컴퓨팅 작업의 구성 요소입니다. 배열 생성에 대한 확실한 이해를 바탕으로 이제 NumPy 에서 더 고급 배열 조작 및 수학 연산을 탐색할 준비가 되었습니다.