Data Analysis/Data Analysis ?

데이터 분석 도구 : NumPy

js-kkk 2025. 2. 27. 17:06

3. 데이터 분석 도구 : NumPy

3-1. NumPy 시작하기

3-1-1. NumPy 개요

💡

NumPy란 Numerical Python의 줄임말로, 대규모 다차원 배열과 행렬 연산을 지원하는 파이썬 라이브러리이다. NumPy는 수학적 연산을 빠르고 효율적으로 수행할 수 있도록 설계되어 있어, 데이터 분석, 머신러닝, 인공지능, 이미지 처리, 신호 처리, 통계 분석 등 여러 분야에서 활용된다.

 

  • NumPy의 주요 특징
    • NumPy의 핵심 자료 구조인 ndarray는 다차원 배열을 효율적으로 관리할 수 있다.
    • 벡터화 연산(Vectorized Operations)을 통해 for문을 사용하지 않고 배열 간 연산을 빠르게 수행할 수 있다.
    • 선형대수, 통계, 푸리에 변환 등 다양한 수학적 연산을 함수로 지원한다.
    • 파이썬 리스트에 비해 적은 메모리를 사용하며, 대규모 데이터를 효과적으로 처리할 수 있다.
      • NumPy는 C 언어로 구현되어 있어, Python 리스트에 비해 대규모 데이터 처리 시 훨씬 빠르다.
      • Python 리스트는 여러 자료형을 저장할 수 있지만, NumPy 배열은 고정된 자료형을 사용해 메모리를 효율적으로 사용한다.항목 Python 리스트 NumPy 배열
        속도 느림 빠름
        메모리 사용 더 많이 사용 덜 사용
        데이터 형식 혼합 가능 동일한 자료형
        연산 방식 for문 등 반복문 필요 벡터화된 연산 지원
    • [참고] NumPy와 Python 리스트 비교

3-1-2. NumPy 설치 및 환경 설정

  • 설치 방법
    • 기본적으로 pip를 사용하여 NumPy를 설치할 수 있다.
pip install numpy

              Anaconda 환경에서는 아래와 같이 설치할 수 있다. 

conda install numpy

 

  • 설치 후 확인
    • NumPy가 제대로 설치되었는지 확인하기 위해 Python에서 NumPy를 불러와 버전을 확인한다.
import numpy as np
print(np.__version__)

출력된 버전을 통해 설치가 완료되었는지 확인할 수 있다.

 

3-1-3. 간단한 NumPy 예제

  1. 배열 생성
import numpy as np
a = np.array([1, 2, 3])
print(a)

 

출력 결과: array([1, 2, 3])

 

  2. 배열 연산

b = np.array([4, 5, 6])
c = a + b
print(c)

 

출력 결과: array([5, 7, 9])

 

  3. 배열의 크기 확인

print(a.shape)  # 배열의 차원
print(a.size)   # 배열의 총 원소 개수

 

출력 결과: shape: (3,), size: 3

 

3-2. ndarray 생성

3-2-1. ndarray 개요

💡

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

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

3**-2-2. ndarray 생성**

  1. 리스트로부터 생성
import numpy as np
arr = np.array([1, 2, 3, 4])
print(arr)

 

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

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

   

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

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

 

 

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

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

 

 

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

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

 

 

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

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

 

 

3-2-3. ndarray 속성

  1. shape : 배열의 모양
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.shape)  # (2, 3)

 

  2. dimension : 배열의 차원

print(arr.ndim)  # 2차원 배열


  3. size : 배열의 크기

print(arr.size)  # 총 6개의 원소

 

  4. 배열의 데이터 타입 확인

print(arr.dtype)  # int64

 

3-3. ndarray 인덱싱 및 슬라이싱

3-3-1. 인덱싱(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)

 

 

3-3-2. 슬라이싱(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]])

 

 

3-3-3. 팬시 인덱싱(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])  # [3, 5, 7]

 

3-3-4. 불리언 인덱싱(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]

 

 

내용추가(25/02/28)

3-4. ndarray 연산

3-4-1. 기본 산술 연산

  • NumPy는 배열 간의 산술 연산을 지원하며, 이는 벡터화되어 빠르게 수행된다.
  • 배열 간 연산은 기본적으로 원소별(element-wise) 연산을 수행한다.
  1. 덧셈(+)
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
print(arr1 + arr2)  # [5, 7, 9]

 

   2. 뺄셈(-)

print(arr1 - arr2)  # [-3, -3, -3]

 

   3. 곱셈(*)

print(arr1 * arr2)  # [4, 10, 18]

 

   4. 나눗셈(/)

print(arr1 / arr2)  # [0.25, 0.4, 0.5]

 

   5. 지수 연산(제곱)

print(arr1 ** 2)  # [1, 4, 9]

 

 

3-4-2. Dot Product (내적) 연산

  • Dot Product(내적) 은 두 배열의 각 원소를 곱한 후 그 결과를 모두 더한 값을 계산하는 연산이다.
  • 벡터와 벡터 간, 또는 행렬과 벡터 간에 내적 연산을 사용할 수 있다.
  1. 1차원 배열(벡터) 간의 Dot Product
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
print(np.dot(arr1, arr2))  # 1*4 + 2*5 + 3*6 = 32

 

   2. 2차원 배열(행렬)과 1차원 배열(벡터) 간의 Dot Product

arr2d = np.array([[1, 2], [3, 4]])
arr1d = np.array([5, 6])
print(np.dot(arr2d, arr1d))
# [1*5 + 2*6, 3*5 + 4*6]
# [17, 39]

 

   3. 2차원 배열(행렬) 간의 Dot Product

arr2d_1 = np.array([[1, 2], [3, 4]])
arr2d_2 = np.array([[5, 6], [7, 8]])
print(np.dot(arr2d_1, arr2d_2))
# [[1*5 + 2*7, 1*6 + 2*8],
#  [3*5 + 4*7, 3*6 + 4*8]]
# [[19, 22],
#  [43, 50]]

 

 

3-4-3. 브로드캐스팅(Broadcasting)

  • 브로드캐스팅은 서로 다른 크기의 배열 간 연산을 가능하게 하는 기능이다. NumPy는 작은 배열을 큰 배열의 크기에 맞춰서 연산을 수행할 수 있게 한다.
  1. 스칼라 값과의 연산
    • 배열 전체에 스칼라 값을 적용하여 연산할 수 있다.
arr = np.array([1, 2, 3])
print(arr + 10)  # [11, 12, 13]

 

 

   2. 다차원 배열과 1차원 배열 간의 브로드캐스팅

  • 다차원 배열에 1차원 배열을 브로드캐스팅 하여 연산할 수 있다.
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
arr1d = np.array([1, 2, 3])
print(arr2d + arr1d)
# [[2, 4, 6],
#  [5, 7, 9]]

 

  3. 3차원 배열과 2차원 배열 간의 브로드캐스팅

arr3d = np.random.rand(3, 1, 4)  # 3x1x4 배열
arr2d = np.random.rand(4, 4)     # 4x4 배열

# 브로드캐스팅을 통해 3차원 배열과 2차원 배열 간 연산 수행
result = arr3d + arr2d
print(result.shape)  # 결과: 3x4x4 배열

 

 

3-4-4. 비교 연산

  • 비교 연산을 사용하여 배열 내 각 요소가 조건을 만족하는지 확인할 수 있다.
  1. 크다/작다 연산
arr = np.array([10, 20, 30])
print(arr > 15)  # [False, True, True]

 

   2. 같다/다르다 연산

print(arr == 20)  # [False, True, False]
print(arr != 20)  # [True, False, True]

 

   3. 배열 간 비교 연산

arr1 = np.array([1, 2, 3])
arr2 = np.array([2, 2, 2])
print(arr1 > arr2)  # [False, False, True]

 

 

3-4-5. 집계 함수

  • NumPy는 배열의 각 요소에 대해 집계(aggregation) 연산을 수행할 수 있는 다양한 함수를 제공한다.
  1. 합계(sum)
arr = np.array([1, 2, 3, 4, 5])
print(arr.sum())  # 15

 

   2. 최대값/최소값(max/min)

print(arr.max())  # 5
print(arr.min())  # 1

 

   3. 평균(mean)

print(arr.mean())  # 3.0

 

   4. 표준편차/분산(std/var)

print(arr.std())  # 표준편차
print(arr.var())  # 분산

 

   5. 누계(cumsum)

print(arr.cumsum())  # [1, 3, 6, 10, 15]

 

   6. 축(axis)을 기준으로 한 연산

  • 2차원 이상의 배열에서는 축(axis) 을 기준으로 연산을 수행할 수 있다.
  • 축 0은 행(row) 을 따라 연산을 수행하고, 축 1은 열(column) 을 따라 연산을 수행한다.
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
print(arr2d.sum(axis=0))  # [5, 7, 9] (각 열의 합)
print(arr2d.sum(axis=1))  # [6, 15] (각 행의 합)

 

 

 

3-5. 통계 기초

3-5-1. 모집단과 표본

  • 모집단(Population): 연구 대상 전체를 의미하며, 모든 데이터를 포함한다. 예를 들어, 특정 나라의 모든 사람의 키 데이터가 모집단에 해당한다.
  • 표본(Sample): 모집단의 일부를 추출한 데이터를 의미하며, 모집단의 특성을 추정하는 데 사용된다.

⇒ 통계 분석에서 모집단을 모두 조사하는 것은 어려우므로, 표본을 사용해 추론 통계를 수행한다.

3-5-2. 기술통계와 추론통계

  • 기술통계(Descriptive Statistics): 데이터를 요약하고 설명하는 데 사용되는 통계 기법이다. 평균, 중앙값, 최빈값, 표준편차 등이 포함된다.
  • 추론통계(Inferential Statistics): 표본 데이터를 사용하여 모집단에 대한 추론을 수행하는 통계 기법이다. 가설 검정, 신뢰 구간 등이 포함된다.

**3-5-**3. 이산값과 연속값

  1. 이산값(Discrete values)
    • 특정한 값을 가지는 데이터로, 정해진 간격이나 구간 안에서만 나타난다.
    • 값들이 셀 수 있는 숫자처럼 구분되어 있어 중간값이 존재하지 않는다.
      • 예: 주사위 눈(1, 2, 3, 4, 5, 6), 사람 수(1명, 2명, 3명 등)
    • 데이터의 값은 유한하거나 명확하게 구분될 수 있다.
  2. 연속값(Continuous values)
    • 측정할 수 있는 모든 값을 포함하는 데이터로, 구간 내의 어떠한 값도 가능하다.
    • 무한한 소수점 단위까지 값을 가질 수 있어, 값 사이에 중간값이 존재할 수 있다.
      • 예: 몸무게(55.5kg, 60.7kg 등), 온도(20.3°C, 21.8°C 등)
    • 데이터의 값은 연속적이어서 값들 간의 경계가 모호하다.

3-5-4. 중심 경향 측도

  • 평균(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

 

 

3-5-5. 산포 측도

  • 분산(Variance): 데이터가 평균으로부터 얼마나 떨어져 있는지를 나타내는 지표로, 값이 클수록 데이터가 퍼져 있음을 의미한다.
print(np.var(arr))  # 125.0

 

  • 표준편차(Standard Deviation): 분산의 제곱근으로, 데이터의 퍼짐 정도를 나타낸다.
print(np.std(arr))  # 11.1803
  • 범위(Range): 데이터의 최댓값과 최솟값의 차이를 의미한다.
print(np.max(arr) - np.min(arr))  # 30

 

 

3-5-6. 확률과 확률분포

  • 확률(Probability): 특정 사건이 발생할 가능성을 0과 1 사이의 값으로 나타낸다. 확률이 1에 가까울수록 해당 사건이 발생할 가능성이 크다.
  • 확률분포(Probability Distribution): 확률 변수가 가질 수 있는 값과 그 값이 나올 확률을 나타내는 함수이다.
    • 예를 들어, 주사위의 확률분포는 각 눈이 나올 확률이 1/6로 균등한 균등분포(Uniform Distribution) 를 따른다.

3-5-7. 정규분포와 균등분포

  • 정규분포(Normal Distribution): 평균을 중심으로 데이터가 대칭적으로 분포하며, 종 모양의 분포를 나타낸다. 정규분포에서는 평균 근처의 값이 자주 나타나고, 양 끝으로 갈수록 빈도가 감소한다.
arr = np.random.randn(1000)  # 평균 0, 표준편차 1인 정규분포 난수 1000개
print(np.mean(arr), np.std(arr))

[ 68-95-99.7 규칙 ]

정규 분포를 나타내는 규칙으로, 경험적인 규칙(empirical rule)이라고도 한다.

3시그마 규칙(three-sigma rule)이라고도 하는데 이 때는 평균에서 양쪽으로 3표준편차의 범위에 거의 모든 값들(99.7%)이 들어간다는 것을 나타낸다.

  • 약 68%의 값들이 평균에서 양쪽으로 1 표준편차 범위 $\mu \pm \sigma$에 존재한다.
  • 약 95%의 값들이 평균에서 양쪽으로 2 표준편차 범위 $\mu \pm 2\sigma$에 존재한다.
  • 거의 모든 값들(실제로는 99.7%)이 평균에서 양쪽으로 3표준편차 범위 $\mu \pm 3\sigma$에 존재한다.

 

 

 

  • 균등분포(Uniform Distribution): 모든 값이 동일한 확률로 발생하는 분포를 의미한다.
arr = np.random.uniform(0, 1, 1000)  # 0과 1 사이의 균등분포 난수 1000개
print(np.mean(arr), np.std(arr))

 

 

3-6. ndarray 정렬

3-6-1. 기본 배열 정렬

  • 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]]

 

 

3-6-2. 특정 축(axis)을 기준으로 정렬

  • 축을 기준으로 정렬할 수 있으며, 축 0은 열(column) 을 기준으로, 축 1은 행(row) 을 기준으로 정렬한다.
  1. 축 0을 기준으로 정렬 (열을 기준으로 정렬)
sorted_arr_axis0 = np.sort(arr2d, axis=0)
print(sorted_arr_axis0)
# [[5, 2, 1],
#  [8, 4, 3]]

 

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

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

 

3-6-3. 인덱스를 반환하는 정렬 (argsort)

  • np.argsort() 함수는 배열을 정렬한 결과의 인덱스 배열을 반환한다. 이 인덱스를 사용하여 배열을 정렬할 수 있다.
  1. 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. 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]]

 

 

 

[ndarray 요소 추가 및 삭제]

  • insert
# np.insert() : 요소의 추가한 새로운 배열을 반환 
arr = np.array([10,20,30])
arr1 = np.append(arr,40)
arr2 = np.insert(arr,1,15)  # 원본배열,
np.append(arr,40)
np.insert(arr,1,15)

print(arr)
# print(arr1)
print(arr2 is arr, arr2)

#[10 20 30]
#False [10 15 20 30]
# 2차원 배열에서 insert()
arr = np.arange(1,13).reshape(3,4)

# print(np.insert(arr,1,10))

print(np.insert(arr, 1, [100,200,300,400],axis=0))
# 원본배열, 삽입할 위치 인덱스, 삽입할 요소, axis(axis=0 : 행기준)
# ([[1,2,3,4],[5,6,7,8],[9,10,11,12]])


#[[  1   2   3   4]
#[100 200 300 400]
#[  5   6   7   8]
#[  9  10  11  12]]
print(np.insert(arr, 1, [100,200,300], axis=1))  # axis=1 : 열 기준
print(np.insert(arr, 1, [100], axis=1))
print(np.insert(arr, 1, 100, axis=1))


#[[  1 100   2   3   4]
# [  5 200   6   7   8]
# [  9 300  10  11  12]]
#[[  1 100   2   3   4]
# [  5 100   6   7   8]
# [  9 100  10  11  12]]
#[[  1 100   2   3   4]
# [  5 100   6   7   8]
# [  9 100  10  11  12]]

 

  • delete
# np.delete():요소를 삭제한 새로운 배열을 반환
arr = np.arange(1,15)
print(np.delete(arr,7))  # 7번째 인덱스 요소 제거 ('7' x)
print(arr)
#[ 1  2  3  4  5  6  7  9 10 11 12 13 14]
#[ 1  2  3  4  5  6  7  8  9 10 11 12 13 14]
# 2차원 배열에서 delete()
arr = np.arange(1,13).reshape(3,4)
print(arr)
print(np.delete(arr,1))            #axis=None : 1차원 배열로 변환 후 삭제
print(np.delete(arr,1,axis=0))     #axis=0 : 입력받은 행 삭제
print(np.delete(arr,1,axis=1))     #axis=1 : 입력받은 열 삭제

#[[ 1  2  3  4]
# [ 5  6  7  8]
# [ 9 10 11 12]]
#[ 1  3  4  5  6  7  8  9 10 11 12]
#[[ 1  2  3  4]
# [ 9 10 11 12]]
#[[ 1  3  4]
# [ 5  7  8]
# [ 9 11 12]]

 

 

3-7. ndarray 병합

3-7-1. 배열 병합이란

💡

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

3-7-2. 축 기준 배열 병합

  • 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]]

 

 

3-7-3. 수직 수평 배열 병합

  • 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]

 

3-7-4. 새로운 축을 따라 배열 병합

  • np.stack(): 새로운 축을 따라 배열을 병합하는 함수이다. 즉, 기존 배열에 차원을 추가한 후 그 축을 따라 배열을 쌓을 수 있다.
  1. 0축을 따라 배열을 병합
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
stacked_arr = np.stack((arr1, arr2), axis=0)
print(stacked_arr)
# [[1, 2, 3],
#  [4, 5, 6]]

 

  2. 1축을 따라 배열을 병합

stacked_arr = np.stack((arr1, arr2), axis=1)
print(stacked_arr)
# [[1, 4],
#  [2, 5],
#  [3, 6]]

 

[추가]

  • np.append()
arr1 = np.arange(1,13).reshape(3,4)
arr2 = np.arange(13,25).reshape(3,4)
arr1, arr2

#(array([[ 1,  2,  3,  4],
#        [ 5,  6,  7,  8],
#        [ 9, 10, 11, 12]]),
# array([[13, 14, 15, 16],
#        [17, 18, 19, 20],
#        [21, 22, 23, 24]]))

# append
print(np.append(arr1, arr2)) 
print(np.append(arr1, arr2, axis = 0)) 
print(np.append(arr1, arr2, axis = 1)) 

#[ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24]
#[[ 1  2  3  4]
# [ 5  6  7  8]
# [ 9 10 11 12]
# [13 14 15 16]
# [17 18 19 20]
# [21 22 23 24]]
#[[ 1  2  3  4 13 14 15 16]
# [ 5  6  7  8 17 18 19 20]
# [ 9 10 11 12 21 22 23 24]]