NumPy 란?

쓰리원·2023년 6월 11일

Data Analysis

목록 보기
1/4
post-thumbnail

NumPy는 Python에서 수치 계산을 빠르고 편리하게 하기 위한 라이브러리입니다.

데이터 분석, 인공지능, 머신러닝, 과학 계산에서 거의 필수적으로 사용됩니다. 특히 리스트(list)보다 훨씬 빠른 계산이 가능하다는 것이 가장 큰 장점입니다.

1. NumPy 주요 특징 요약

1. 다차원 배열(ndarray) 지원

ndarray란 NumPy의 핵심 자료 구조로, n차원 배열을 의미한다. Python의 리스트와 유사하지만, 고정된 크기와 단일 데이터 타입을 가진다. 배열의 각 차원을 축(axis) 이라고 하며, 각 축의 크기는 배열의 모양(shape) 이다.

  • ndarray의 특징
    • 1차원, 2차원, …, 다차원 배열을 생성할 수 있다.
    • 배열 내의 모든 원소는 동일한 데이터 타입이어야 한다.
    • 벡터화된 연산으로 빠르고 효율적인 수치 계산이 가능하다.

2. 벡터화 연산(Vectorized Operations)

for문 없이 배열 전체를 한 번에 계산할 수 있다.
Python 리스트보다 훨씬 빠르게 연산을 수행한다.

	a = np.array([1, 2, 3])
    b = np.array([4, 5, 6])
    c = a + b
    print(c)
    
    - 출력 결과: `array([5, 7, 9])`

3. 다양한 수학 함수 제공

합(sum), 평균(mean), 최대값(max), 최소값(min) 등 통계 함수를 제공한다.
선형대수, 행렬 연산, 푸리에 변환 등 다양한 수학 계산을 지원한다.

4. 메모리 사용이 효율적

데이터를 연속된 메모리 공간에 저장하여 Python 리스트보다 메모리를 적게 사용한다.
대용량 데이터 처리에 적합하다.

5. Python 리스트와 NumPy 배열 비교

  • NumPy는 C 언어로 구현되어 있어, Python 리스트에 비해 대규모 데이터 처리 시 훨씬 빠르다.
  • Python 리스트는 여러 자료형을 저장할 수 있지만, NumPy 배열은 고정된 자료형을 사용해 메모리를 효율적으로 사용한다.
항목Python 리스트NumPy 배열
속도느림빠름
메모리 사용많음적음
자료형혼합 가능동일한 자료형만 저장
연산반복문(for) 필요벡터화 연산 지원

2. ndarray 생성

1. 리스트로부터 생성

    import numpy as np
    
    arr = np.array([1, 2, 3, 4])
    print(arr)

    [1 2 3 4]

2. 0으로 채운 배열 생성 (np.zeros())

  • 모든 값이 0인 배열을 생성한다.
    arr = np.zeros((2, 3))  # 2x3 배열
    print(arr)
    [[0. 0. 0.]
 	[0. 0. 0.]]

3. 1로 채운 배열 생성 (np.ones())

  • 모든 값이 1인 배열을 생성한다.
    arr = np.ones((3, 2))  # 3x2 배열
    print(arr)
    [[1. 1.]
 [1. 1.]
 [1. 1.]]

4. 연속적인 값으로 배열 생성 (np.arange())

  • 주어진 범위 내에서 연속적인 값으로 구성된 배열을 생성한다.
    arr = np.arange(0, 10, 2)  # 0부터 9까지 2씩 증가하는 값
    print(arr)
    [0 2 4 6 8]

5. 등간격으로 배열 생성 (np.linspace())

  • 시작과 끝을 포함하여 지정한 개수만큼의 값으로 배열을 생성한다.
    arr = np.linspace(0, 1, 5)  # 0에서 1까지 5개의 등간격 값
    print(arr)
    [0.   0.25 0.5  0.75 1.  ]

6. 정규 분포로 난수 배열 생성 (np.random.randn())

  • 평균 0, 표준편차 1인 정규 분포로 난수를 생성한다.
    arr = np.random.randn(2, 3)  # 2x3 배열
    print(arr)
    [[-0.21923695  0.19261846  0.37270454]
 [-1.27010038 -1.1695589   0.24189817]]

3. 인덱싱(Indexing)

Python의 리스트처럼 ndarray도 인덱스를 사용하여 배열의 특정 값을 선택할 수 있다. NumPy 배열은 0부터 시작하는 인덱스를 사용하며, 다차원 배열에서도 각 차원별로 인덱스를 지정할 수 있다.

1. 1차원 배열 인덱싱

    import numpy as np
    arr = np.array([10, 20, 30, 40, 50])
    print(arr[0])  # 0번째 요소 출력 (10)
    print(arr[2])  # 2번째 요소 출력 (30)

2. 2차원 배열 인덱싱

  • 2차원 배열에서 요소에 접근할 때는 행과 열의 인덱스를 모두 지정한다.
    arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    print(arr[0, 1])  # 0번째 행, 1번째 열의 요소 출력 (2)
    print(arr[2, 2])  # 2번째 행, 2번째 열의 요소 출력 (9)

3. 3차원 배열 인덱싱

  • 3차원 배열의 경우, 각 차원에 대해 인덱스를 지정한다.
arr = np.array([
    [[1, 2, 3], [4, 5, 6]], 
    [[7, 8, 9], [10, 11, 12]]
    ])
    print(arr[1, 0, 2])  # 1번째 차원, 0번째 행, 2번째 열의 요소 출력 (9)

4. 슬라이싱(Slicing)

Python 리스트의 슬라이싱과 유사하게 ndarray도 :를 사용하여 슬라이싱을 할 수 있다.

1. 1차원 배열 슬라이싱

  • 시작 인덱스와 끝 인덱스를 사용하여 배열의 일부를 선택할 수 있다.
    arr = np.array([10, 20, 30, 40, 50])
    print(arr[1:4])  # 1번째 인덱스부터 3번째 인덱스까지의 값 출력 ([20, 30, 40])
    print(arr[:3])   # 처음부터 2번째 인덱스까지 출력 ([10, 20, 30])

2. 2차원 배열 슬라이싱

  • 2차원 배열에서 슬라이싱을 사용하여 부분 배열을 추출할 수 있다.
    arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    print(arr[1:, :2])  # 1번째 행부터 끝까지, 0번째와 1번째 열만 출력 ([[4, 5], [7, 8]])

3. 3차원 배열 슬라이싱

  • 3차원 배열에서 각 차원별로 슬라이싱을 지정할 수 있다.
arr = np.array([
    [[1, 2, 3], [4, 5, 6]], 
    [[7, 8, 9], [10, 11, 12]]
    ])
    print(arr[:, 1, :2])  # 각 차원에서 1번째 행의 처음 두 열 출력 ([[4, 5], [10, 11]])

5. 팬시 인덱싱(Fancy Indexing)

팬시 인덱싱을 통해 정수 배열을 사용하여 여러 위치의 값을 한 번에 선택할 수 있다.

1. 정수 배열을 사용한 팬시 인덱싱

    arr = np.array([10, 20, 30, 40, 50])
    idx = [0, 2, 4]  # 0번째, 2번째, 4번째 인덱스를 선택
    print(arr[idx])   # [10, 30, 50]

2. 2차원 배열에서 팬시 인덱싱

- 행과 열의 인덱스를 각각 배열로 지정하여 선택할 수 있다.
    arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    rows = [0, 1, 2]
    cols = [2, 1, 0]
    print(arr[rows, cols])  # 각 행과 열을 묶어서 [(0, 2), (1, 1), (2, 0)]

    [3 5 7]

6. 불리언 인덱싱(Boolean Indexing)

조건을 만족하는 배열의 요소를 선택하는 방법이다.

1. 불리언 배열을 사용한 인덱싱

  • 조건을 만족하는 값만 추출할 수 있다.
    arr = np.array([10, 20, 30, 40, 50])
    print(arr[arr > 30])  # [40, 50]

2. 2차원 배열에서의 불리언 인덱싱

  • 조건을 적용하여 2차원 배열에서도 특정 요소를 선택할 수 있다.
    arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    print(arr[arr > 4])  # [5, 6, 7, 8, 9]

7. ndarray 정렬

  • NumPy 배열 정렬은 np.sort() 함수를 사용하여 수행된다. 이 함수는 배열의 복사본을 생성하여 정렬된 배열을 반환하며, 기본적으로 오름차순으로 정렬된다.

1. 1차원 배열 정렬

  • 배열의 원소를 오름차순으로 정렬한다.
    import numpy as np
    arr = np.array([30, 10, 20, 40, 50])
    sorted_arr = np.sort(arr)
    print(sorted_arr)  # [10, 20, 30, 40, 50]

2. 내림차순 정렬

  • [::-1] 슬라이싱을 사용하여 내림차순으로 정렬할 수 있다.
    sorted_arr_desc = np.sort(arr)[::-1]
    print(sorted_arr_desc)  # [50, 40, 30, 20, 10]

3. 2차원 배열 정렬

  • 2차원 배열은 각 행(row) 또는 열(column)을 기준으로 정렬할 수 있다. 기본적으로 각 행을 기준으로 정렬이 수행된다.
    arr2d = np.array([[5, 2, 3], [8, 4, 1]])
    sorted_arr2d = np.sort(arr2d)  # 행 단위로 정렬
    print(sorted_arr2d)
    # [[2, 3, 5],
    #  [1, 4, 8]]

8. 특정 축(axis)을 기준으로 정렬

  • 축을 기준으로 정렬할 수 있으며, 축 0은 열(column) 을 기준으로, 축 1은 행(row) 을 기준으로 정렬한다.

1. 축 0을 기준으로 정렬 (열을 기준으로 정렬)

	arr2d = np.array([[5, 2, 3], [8, 4, 1]])
    sorted_arr_axis0 = np.sort(arr2d, axis=0)
    print(sorted_arr_axis0)
    
    # [[5, 2, 1],
    #  [8, 4, 3]]

2. 축 1을 기준으로 정렬 (행을 기준으로 정렬)

	arr2d = np.array([[5, 2, 3], [8, 4, 1]])
    sorted_arr_axis1 = np.sort(arr2d, axis=1)
    print(sorted_arr_axis1)
    # [[2, 3, 5],
    #  [1, 4, 8]]

9. 인덱스를 반환하는 정렬 (argsort)

  • np.argsort() 함수는 배열을 정렬한 결과의 인덱스 배열을 반환한다. 이 인덱스를 사용하여 배열을 정렬할 수 있다.

1차원 배열에서 argsort 사용

arr = np.array([30, 10, 20])
sorted_indices = np.argsort(arr)
print(sorted_indices)  # [1, 2, 0] (정렬된 순서의 인덱스)

# 인덱스를 사용하여 배열을 정렬
print(arr[sorted_indices])  # [10, 20, 30]

2차원 배열에서 argsort 사용

  • 특정 축을 기준으로 인덱스를 반환할 수 있다.
arr2d = np.array([[3, 1, 2], [6, 4, 5]])
sorted_indices = np.argsort(arr2d, axis=1)  # 각 행을 기준으로 인덱스를 반환
print(sorted_indices)
# [[1, 2, 0],
#  [1, 2, 0]]

10. ndarray 병합

배열 병합은 여러 개의 배열을 연결하여 하나의 배열로 만드는 방법이다. NumPy에서 배열을 병합하는 방법은 np.concatenate(), np.vstack(), np.hstack() 등의 함수를 사용한다.

1. 축 기준 배열 병합

  • np.concatenate(): 주어진 축(axis)을 기준으로 배열을 병합하는 함수이다. 기본적으로 축 0을 기준으로 병합한다.

1. 1차원 배열 병합

  • 두 개 이상의 1차원 배열을 연결할 수 있다.
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
merged_arr = np.concatenate((arr1, arr2))
print(merged_arr)  # [1, 2, 3, 4, 5, 6]

2. 2차원 배열 병합 (축 0)

  • 행을 기준으로 배열을 병합할 수 있다. 이 경우 배열들의 열 개수가 같아야 한다.
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
merged_arr = np.concatenate((arr1, arr2), axis=0)
print(merged_arr)
# [[1, 2],
#  [3, 4],
#  [5, 6],
#  [7, 8]]

3. 2차원 배열 병합 (축 1)

  • 열을 기준으로 배열을 병합할 수 있다. 이 경우 배열들의 행 개수가 같아야 한다.
merged_arr = np.concatenate((arr1, arr2), axis=1)
print(merged_arr)
# [[1, 2, 5, 6],
#  [3, 4, 7, 8]]

2. 수직 수평 배열 병합

  • np.vstack(): 수직으로 배열을 병합하는 함수로, 배열을 행(row) 기준으로 쌓는다. 여러 배열을 위아래로 병합할 수 있다.
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
merged_arr = np.vstack((arr1, arr2))
print(merged_arr)
# [[1, 2, 3],
#  [4, 5, 6]]
  • np.hstack(): 수평으로 배열을 병합하는 함수로, 배열을 열(column) 기준으로 쌓는다. 여러 배열을 좌우로 병합할 수 있다.
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
merged_arr = np.hstack((arr1, arr2))
print(merged_arr)  # [1, 2, 3, 4, 5, 6]

11. 중심 경향 측도

  • 평균(Mean): 모든 데이터 값을 더한 후 데이터의 개수로 나눈 값이다.
    arr = np.array([10, 20, 30, 40])
    print(np.mean(arr))  # 25.0
  • 중앙값(Median): 데이터 값을 크기 순서대로 정렬했을 때 중앙에 위치한 값이다.
    print(np.median(arr))  # 25.0
  • 최빈값(Mode): 데이터에서 가장 자주 등장하는 값이다. NumPy에는 내장 함수가 없지만, scipy.stats 패키지를 이용해 계산할 수 있다.
    from scipy import stats
    
    arr = np.array([10, 20, 20, 30, 40])
    print(stats.mode(arr))  # Mode: 20

12. 산포 측도

  • 분산(Variance): 데이터가 평균으로부터 얼마나 떨어져 있는지를 나타내는 지표로, 값이 클수록 데이터가 퍼져 있음을 의미한다.
    print(np.var(arr))  # 125.0
  • 표준편차(Standard Deviation): 분산의 제곱근으로, 데이터의 퍼짐 정도를 나타낸다.
    print(np.std(arr))  # 11.1803
  • 범위(Range): 데이터의 최댓값과 최솟값의 차이를 의미한다.
    print(np.max(arr) - np.min(arr))  # 30
profile
가장 아름다운 정답은 서로의 협업안에 있다.

0개의 댓글