본문 바로가기

PYTHON-BACK

#파이썬 기초 9일차_2

728x90

Numpy (Numerical Python)

1. Numpy 개요

1-1. Numpy란?

  • NumPy(Numerical Python)는 고성능의 과학 계산과 데이터 분석을 위한 기본 패키지입니다. 주로 행렬이나 대규모의 다차원 배열을 쉽게 처리할 수 있게 해주며, 계산 과학(Computational Science) 분야의 복잡한 연산을 지원한다. 또한, SciPy, Matplotlib, Pandas 등과 같은 라이브러리에서 채택되어 더 복잡한 연산을 쉽게 처리할 수 있도록 돕고있다.

1-2. NumPy에서 제공하는 기능

    • ndarray: 빠르고 메모리를 효율적으로 사용하며, 벡터 산술 연산과 세련된 브로드캐스팅 기능을 제공하는 다차원 배열을 지원
    • 표준 수학 함수: 반복문 없이 전체 데이터 배열에 대해 빠른 연산을 제공하는 표준 수학 함수를 포함
    • 데이터 입출력 도구: 배열 데이터를 디스크에 쓰거나 읽을 수 있는 도구와 메모리에 올려진 파일을 사용하는 도구를 제공
    • 선형대수, 난수 발생기, 푸리에 변환: 이와 같은 수학적 기능을 지원
    • C, C++, 포트란 통합: 이러한 언어로 작성된 코드를 통합하는 도구를 제공하며, 사용하기 편한 C API를 제공
    • 저급 언어 데이터 전달: 데이터를 다른 저급 언어로 쓰여진 외부 라이브러리에 쉽게 전달할 수 있도록 지원
    • 외부 라이브러리 데이터 수용: 외부 라이브러리에서 반환된 데이터를 파이썬의 NumPy 배열 형태로 불러올 수 있게 해준다.
    • 레거시 코드 래핑: 파이썬을 사용하여 레거시 C/C++/포트란 기반의 코드를 동적이며 쉽게 사용할 수 있는 인터페이스로 래핑할 수 있도록 한다.
1-3. Numpy를 잘 활용하려면
 
  • NumPy는 자체적으로 고수준의 데이터 분석 기능을 제공하지 않으므로, NumPy 배열과 배열 기반의 컴퓨팅에 대한 이해가 선행되어야 한다. 이렇게 하면 더 상위 레벨에서 데이터 분석과 같은 기능을 제공하는 Pandas 등의 도구들을 더욱 효율적으로 사용할 수 있을 것이다.
 

1-4. 대부분의 데이터 분석 애플리케이션에서 중요하게 사용되는 기능

  • 벡터 배열 상에서의 데이터 개조: 정제, 부분집합, 필터링, 변형, 이종 연산의 빠른 수행.
  • 일반적인 배열 처리 알고리즘: 정렬, 유일 원소 찾기, 집합 연산 등.
  • 통계 표현과 데이터 요약: 효과적인 통계 표현과 데이터의 수집/요약.
  • 데이터 정렬과 관계 조작: 이종 데이터 묶음을 병합하고 엮기 위한 데이터 정렬과 관계 조작.
  • 조건절 배열 표현: if ~ elif ~ else 포함 반복문 대신 사용 가능한 조건절 표현.
  • 데이터 처리: 데이터 그룹 전체에 적용할 수 있는 수집, 변형, 함수 적용 등의 기능.

2. Numpy 실습 예제

2-1. ndarray (n-Dimension Array)
 

넘파이는 코렙에 설치되어있다.

!pip list를 통해서 설치 버전 및 다양한 라이브러리 설치된것을 확인할 수 있다.

import numpy as np
  • ndarray 배열은 산술 연산이 가능함
  • ndarray 배열은 각 차원의 크기를 알려주는 shape라는 튜플을 가짐
  • ndarray 배열은 배열에 저장된 자료형을 알려주는 dtype이라는 객체를 가짐
data = np.random.randn(2, 3)
print(data)

[[ 0.95914742  0.39933286  1.1382152 ]
 [ 0.2563537   0.94847476 -0.02540403]]

data

array([[ 0.95914742,  0.39933286,  1.1382152 ],
       [ 0.2563537 ,  0.94847476, -0.02540403]])

 

원소끼리 1대1로 연산됨

data * 10

array([[ 9.59147416,  3.99332856, 11.38215198],
       [ 2.56353697,  9.4847476 , -0.25404026]])

data + 10

array([[10.95914742, 10.39933286, 11.1382152 ],
       [10.2563537 , 10.94847476,  9.97459597]])

data + data

array([[ 1.91829483,  0.79866571,  2.2764304 ],
       [ 0.51270739,  1.89694952, -0.05080805]])

data.shape

(2,3)

 

데이터의 dtype은 한개로 동일함

data.dtype

dtype('float64')

 

  • ndarray의 생성과 사용 (우리가 가지고 있는 데이터를 이용하여 ndarray 만들기)
  • NumPy는 배열의 모든 요소가 동일한 데이터 타입을 가지도록 변환하기 때문에, 정수와 실수가 섞여 있는 경우 더 포괄적인 데이터 타입인 실수형으로 변환시킨다.(아래 코드의 경우)
data1 = [6, 7.5, 8, 0, 3]  # 정수와 실수가 섞여 있지만, NumPy 배열로 변환 시 모두 실수형이 됨
arr1 = np.array(data1)
arr1

array([6. , 7.5, 8. , 0. , 3. ])

 

arr1.ndim # 몇 차원인지 보여주는 것

1

data1 # 입력한 소스임으로 변동이 없다.

[6, 7.5, 8, 0, 3]

 

  • 같은 길이의 리스트가 담겨있는 순차 데이터는 다차원 배열로 변환이 가능함
data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]
arr2 = np.array(data2)
arr2

array([[1, 2, 3, 4],
       [5, 6, 7, 8]])

arr2.ndim

2

arr2.shape

(2,4)

 

  • 명시적으로 지정하지 않는 한 np.array는 생성될 때 적절한 자료형을 지정하여 적용함
arr1.dtype

dtype('float64')

arr2.dtype

dtype('int64')

 

  • 새로운 배열을 생성하기 위한 다양한 함수 보유
np.zeros(10)               # 10개의 요소가 0으로 채워진 1차원 배열 생성

array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

np.zeros((3, 6))            # 6개의 요소를 가진 1차원 배열이 3개가 포함된 2차원 배열 생성

array([[0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0.]])

np.ones((3,4))

array([[1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.]])

np.empty((2, 3, 2))              # empty 함수는 초기화되지 않은 배열 생성. 원하는 형태를 정의한 튜플을 넘기면 해당 형태로 생성, (면, 행, 열) 순서로 형태를 정의한 튜플을 넘김

array([[[6.77913732e-310, 0.00000000e+000],
        [0.00000000e+000, 0.00000000e+000],
        [0.00000000e+000, 0.00000000e+000]],

       [[0.00000000e+000, 0.00000000e+000],
        [0.00000000e+000, 0.00000000e+000],
        [0.00000000e+000, 0.00000000e+000]]])

 

  • 파이썬의 range 함수의 배열 버전인 arange 함수
np.arange(15)

array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])

range(15)
print(type(range(0 ,15)))

range(0, 15)

<class 'range'>

  • 데이터 타입 확인
arr0 = np.array([1., 2, 3])
print(arr0.dtype)
print(arr0)

float64

[1. 2. 3.]

arr1 = np.array([1, 2, 3], dtype=np.float64)
print(arr1.dtype)
print(arr1)

float64

[1. 2. 3.]

arr2 = np.array([1, 2, 3], dtype=np.int32)
print(arr2.dtype)
print(arr2)

int32

[1 2 3]

 

arr = np.array([3.7, -1.2, -2.6, 0.5, 12.9, 10.1])
arr1 = arr.astype(np.int32)
print(arr1)

[ 3 -1 -2 0 12 10]

import copy

arr2 = arr1
arr2[0] = 10
print(arr2)
print(arr1)

[10 -1 -2 0 12 10]

[10 -1 -2 0 12 10]

arr3 = copy.copy(arr1)
arr3[0] = 20
print(arr3)
print(arr1)

[20 -1 -2 0 12 10]

[10 -1 -2 0 12 10]

# 문자열로 이루어진 배열 생성 (dtype=np.string_)
numeric_strings = np.array(['1.25', '-9.6', '42'], dtype=np.string_)
print(numeric_strings)
numeric_strings.astype(float)

[b'1.25' b'-9.6' b'42']
array([ 1.25, -9.6 , 42.  ])

# 정수 배열 생성
int_array = np.arange(10)
print(int_array.dtype)
# 실수형(float64) 배열 생성
calibers = np.array([.22, .270, .357, .380, .44, .50], dtype=np.float64)
print(calibers.dtype)
int_array.astype(calibers.dtype)

int64
float64
array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])

# uint32 타입의 배열 생성
empty_uint32 = np.empty(8, dtype='u4')
empty_uint32

array([         0, 1075314688,          0, 1075707904,          0,
       1075838976,          0, 1074266112], dtype=uint32)

 

  • 산술 연산
  • NumPy 배열은 기본적으로 배열의 원소들이 1대1로 대응하여 계산
arr = np.array([[1., 2., 3.], [4., 5., 6.]])
arr

array([[1., 2., 3.],
       [4., 5., 6.]])

# 배열 간의 곱셈 (원소별 곱셈)
arr * arr

array([[ 1.,  4.,  9.],
       [16., 25., 36.]])

# 배열의 각 원소를 1로 나눔
1 / arr

array([[1.        , 0.5       , 0.33333333],
       [0.25      , 0.2       , 0.16666667]])

 

스칼라

# 배열의 각 원소에 대해 제곱근 연산
arr ** 0.5

array([[1.        , 1.41421356, 1.73205081],
       [2.        , 2.23606798, 2.44948974]])

 

배열 간의 비교 연산

# 두 번째 2x3 배열 생성
arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])
arr2

 

array([[ 0.,  4.,  1.],
       [ 7.,  2., 12.]])

 

# 배열 간의 비교 (arr2가 arr보다 큰지 비교)
arr2 > arr

array([[False,  True, False],
       [ True, False,  True]])

2-2. 인덱싱과 슬라이싱

  • 기본 인덱싱
  • 기본 배열 처리시 인덱스를 기준으로 처리한다.
arr = np.arange(10)
arr

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

arr[5]

5

arr[5:8]

array([5, 6, 7])

arr[5:8] = 12
arr

array([ 0,  1,  2,  3,  4, 12, 12, 12,  8,  9])

arr_slice = arr[5:8]
arr_slice

array([12, 12, 12])

arr_slice[1] = 12345
arr

array([    0,     1,     2,     3,     4,    12, 12345,    12,     8,
           9])

arr_slice[:] = 64
arr

array([ 0,  1,  2,  3,  4, 64, 64, 64,  8,  9])

arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
arr2d[2]

array([7, 8, 9])

arr2d[0][2]

3

arr2d

array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

 

내일 이어서 작성

728x90

'PYTHON-BACK' 카테고리의 다른 글

#파이썬 기초 10일차_2  (0) 2024.07.10
#파이썬 기초 10일차_1  (0) 2024.07.10
#파이썬 기초 9일차_1  (0) 2024.07.09
#파이썬 기초 8일차_2  (0) 2024.07.08
#파이썬 기초 8일차_1  (1) 2024.07.08