NumPy - 1. 기초

2025. 1. 20. 18:33프로그래밍 (확장)/Python-NumPy

 

NumPy란 무엇인가?

  1. NumPy의 정의와 역할 NumPy는 Python에서 사용되는 강력한 라이브러리로, 다차원 배열과 행렬을 쉽게 처리할 수 있도록 설계되었습니다. 또한, 고속으로 작동하는 수학적 연산 기능을 제공합니다.
    • 주요 역할:
      • 대규모 데이터 배열을 효율적으로 다루기.
      • 과학적 계산과 데이터 분석에 필수적인 수학 연산 지원.
  2. Python 표준 리스트와의 차이점
    • 속도: NumPy 배열은 C 언어로 작성되어 Python 리스트보다 훨씬 빠르게 작동합니다.
    • 메모리 효율성: NumPy 배열은 동일한 데이터 타입을 사용하므로 메모리 사용량이 적습니다.
    • 다차원 지원: Python 리스트는 기본적으로 1차원 배열만 지원하지만, NumPy는 다차원 배열 처리가 가능합니다.
    • 풍부한 기능: NumPy는 통계, 선형대수 등 다양한 수학 연산을 쉽게 구현할 수 있습니다.
  3. NumPy가 데이터 과학과 과학 계산에서 중요한 이유
    • 데이터 전처리, 통계 계산, 머신러닝 모델링 등에서 필수적인 도구.
    • Pandas, SciPy, Matplotlib 등의 다른 라이브러리와 잘 연동되어 강력한 데이터 분석 도구로 활용 가능.

NumPy 설치 방법

  1. NumPy 설치 과정
    • pip install numpy 명령어를 사용하여 설치합니다.
      pip install numpy
      
    • 설치가 완료되면 Python 환경에서 NumPy를 불러와 확인합니다:
      import numpy as np
      print(np.__version__)
      
  2. 설치 오류 해결 방법
    • Python과 pip 버전 확인:
      python --version
      pip --version
      
    • 설치 오류 발생 시, pip install --upgrade pip로 pip 버전을 업그레이드하거나, 가상 환경을 사용하는 것을 권장합니다.
    • 보안 관련 주의사항: pip install 명령어 사용 시 반드시 신뢰할 수 있는 소스(PyPI)를 사용해야 합니다.
  3. 버전 확인 및 업데이트
    • 설치된 NumPy 버전을 확인하려면:
      import numpy as np
      print(np.__version__)
      
    • 최신 버전으로 업데이트:
      pip install numpy --upgrade
      

NumPy 배열 생성

  1. numpy.array를 사용한 배열 생성
    • NumPy 배열은 numpy.array() 함수를 통해 생성합니다.
      import numpy as np
      arr = np.array([1, 2, 3])
      print(arr)  # [1 2 3]
      
    • 다차원 배열 생성:
      arr_2d = np.array([[1, 2], [3, 4]])
      print(arr_2d)
      # [[1 2]
      #  [3 4]]
      
  2. 다양한 데이터 타입 설정 (dtype)과 변환 (astype)
    • dtype 매개변수를 사용해 데이터 타입을 지정:
      arr = np.array([1.5, 2.3, 3.7], dtype='float32')
      print(arr.dtype)  # float32
      
    • 데이터 타입 변환:
      arr = np.array([1, 2, 3])
      float_arr = arr.astype('float64')
      print(float_arr)  # [1. 2. 3.]
      
    • dtype의 다양한 옵션들:
      • int32, int64: 정수형 데이터 타입.
      • float32, float64: 실수형 데이터 타입.
      • complex64, complex128: 복소수 데이터 타입.
      • bool: Boolean 데이터 타입.
      arr = np.array([0, 1, 2], dtype='bool')
      print(arr)  # [False  True  True]
      
  3. 배열 속성 확인
    • 배열의 주요 속성:
      arr = np.array([[1, 2, 3], [4, 5, 6]])
      print(arr.shape)  # (2, 3)
      print(arr.size)   # 6
      print(arr.ndim)   # 2
      print(arr.dtype)  # int64
      
  4. NumPy의 C 기반 구현이 성능에 미치는 영향
    • Python 리스트와 NumPy 배열의 속도 비교 (timeit 모듈 사용):
      import numpy as np
      import timeit
      
      size = 1000000
      python_list = list(range(size))
      numpy_array = np.arange(size)
      
      python_time = timeit.timeit(lambda: [x * 2 for x in python_list], number=10)
      numpy_time = timeit.timeit(lambda: numpy_array * 2, number=10)
      
      print("Python 리스트 소요 시간:", python_time)
      print("NumPy 배열 소요 시간:", numpy_time)
      
    • 결과: NumPy 배열이 Python 리스트보다 훨씬 빠르게 동작합니다.
  5. 메모리 사용량 비교
    • Python 리스트와 NumPy 배열의 메모리 사용량 측정:
      import numpy as np
      import sys
      
      size = 1000000
      python_list = list(range(size))
      numpy_array = np.arange(size)
      
      python_memory = sys.getsizeof(python_list)
      numpy_memory = numpy_array.nbytes
      
      print("Python 리스트 메모리 사용량:", python_memory, "bytes")
      print("NumPy 배열 메모리 사용량:", numpy_memory, "bytes")
      
    • 결과: NumPy 배열이 메모리를 더 효율적으로 사용합니다.

배열 초기화 방법

  1. 다양한 초기화 함수
    • np.zeros: 모든 값이 0인 배열 생성:
      zeros = np.zeros((2, 3))
      print(zeros)
      # [[0. 0. 0.]
      #  [0. 0. 0.]]
      
    • np.ones: 모든 값이 1인 배열 생성:
      ones = np.ones((3, 2))
      print(ones)
      # [[1. 1.]
      #  [1. 1.]
      #  [1. 1.]]
      
    • np.full: 지정된 값으로 초기화:
      full = np.full((2, 2), 7)
      print(full)
      # [[7 7]
      #  [7 7]]
      
    • np.eye: 단위 행렬 생성:
      eye = np.eye(3)
      print(eye)
      # [[1. 0. 0.]
      #  [0. 1. 0.]
      #  [0. 0. 1.]]
      
  2. arange와 linspace를 활용한 범위 배열 생성
    • np.arange: 일정 간격의 숫자 생성:
      arange = np.arange(0, 10, 2)
      print(arange)  # [0 2 4 6 8]
      
    • np.linspace: 구간을 나눠 배열 생성:
      linspace = np.linspace(0, 1, 5)
      print(linspace)  # [0.   0.25 0.5  0.75 1.  ]
      
  3. 난수 배열 생성
    • np.random.rand: 0과 1 사이의 난수 생성:
      rand = np.random.rand(3, 2)
      print(rand)
      
    • NumPy 1.17.0 이후 권장되는 Generator 사용:
      from numpy.random import default_rng
      rng = default_rng()
      rand = rng.random((3, 2))
      print(rand)
      
    • np.random.randint: 특정 범위의 정수 생성:
      randint = np.random.randint(1, 10, (2, 3))
      print(randint)
      
    • np.random.normal: 정규분포를 따르는 난수 생성:
      normal = np.random.normal(0, 1, (2, 2))
      print(normal)
      

배열 인덱싱과 슬라이싱

  1. 기본 인덱싱과 슬라이싱
    • 1차원 배열:
      arr = np.array([10, 20, 30, 40])
      print(arr[1])   # 20
      print(arr[1:3]) # [20 30]
      
    • 다차원 배열:
      arr = np.array([[1, 2, 3], [4, 5, 6]])
      print(arr[0, 1])   # 2
      print(arr[:, 1])   # [2 5]
      
  2. 조건부 인덱싱 (Boolean Indexing)
    • 조건에 따라 배열의 값을 선택:
      arr = np.array([1, 2, 3, 4, 5])
      print(arr[arr > 3])  # [4 5]
      
  3. 고급 인덱싱 (Fancy Indexing)
    • 배열이나 리스트를 사용해 원하는 요소를 선택:
      arr = np.array([10, 20, 30, 40])
      indices = [0, 2, 3]
      print(arr[indices])  # [10 30 40]