from palette import colorful_colors

[Numpy] ndarray, 연산, 인덱싱, 통계함수 본문

CS 학부과목/Python

[Numpy] ndarray, 연산, 인덱싱, 통계함수

colorful-palette 2023. 1. 29. 04:25

<목차>
1. Numpy(넘파이)란?
2. ndarray 클래스 구성
3. ndarray 속성 살펴보기
4. 넘파이 연산
5. ndarray 요소 접근 방법
6. 넘파이 통계 함수

1. Numpy(넘파이)란?

  • 대량의 데이터 수치계산, 파이썬에 자료 제공하기 위한 라이브러리다. 수치계산에 최적화되어 있어 기존 파이썬의 자료형들보다ex) list 데이터를 빠르게 처리할 수 있다.
  • 배열(array)형태를 다루는 라이브러리
    - ndarray라는 클래스의, 연속된 메모리공간에 동일한 데이터를 저장한다.
    - 파이썬 표준 라이브러리가 아닌 외부 라이브러리이므로 추가 설치가 필수다.
!pip install numpy


터미널에서 다음과 같은 명령어로 설치가 가능하다.

import numpy as np

코드에 import 할 때는 국롤로 np로 이름을 바꿔 쓴다.


2. ndarray 클래스 구성

넘파이는 ndarray라는 새로운 클래스를 제공해준다. 파이썬의 list, tuple, dictionary와 같은 변수 저장 자료형이라고 생각하면 된다.

2-1. list와 ndarray 비교

대표적인 파이썬의 데이터 저장 자료형인 리스트를 생각해보자.
가장 큰 차이점이라면, ndarray는 배열에 담은 자료형을 동일하게 통일한다.(제일 큰 자료형으로) ex) int와 float를 둘 다 담으면 float로 변경
또한 리스트와 달리 추가로 공간 할당이 불가능하다.
사실 리스트는 리스트에 변수를 마음대로 추가하고 삭제할 수 있어 (.push(), pop()함수를 제공하니깐) 진정한 배열이라고 할 수 없다.
파이썬은 기본적으로 동적 할당 구조로, 리스트는 데이터의 주소만 담고 있다. (그래서 느리다)
파이썬의 리스트는 주소로 접근하지만 배열은 바이트 크기만큼 이동해서 더 빠르다! (C의 배열 접근 방식과 비슷하다.)


ndarray 특징 예시:

arr1 = np.array([1,2,3], dtype = 'int32')	# np.array로 ndarray 배열을 만들 수 있다.  
#type을 지정할 수 있다.아무것도 안 정하면 default값으로 정수는 int64를 가져온다. 
arr2 = np.array([1, 2.0, 3])    		# 데이터가 제일 큰 타입(float)으로 동일하게 형변환 
arr3 = np.array([1,'A',3.1, False]) 		# 제일 큰 타입인 문자(유니코드U32)로 모두 형변환된다.
arr4 = np.array([[1,2,3],[4,5,6]])		# 2차원 배열을 생성한다.

print(arr1, arr2, arr3, arr4)


# 출력결과:
# [1 2 3] [1. 2. 3.] ['1' 'A' '3.1' 'False'] [[1 2 3][4 5 6]]

ndarray는 list와 달리 쉼표가 없다는점이 차이점이다.

2-2. ndarray 클래스 구성

그렇다면 넘파이에서 새롭게 제공하는 배열 형태의 클래스, ndarray의 대표적인 속성과 메서드를 살펴보자.
ndarray도 클래스이니 속성과 메서드를 가지고 있다.
속성 (내가 가지고 있는 ndarray 클래스에 대한 정보):
- np.data: 메모리의 저장된 데이터의 시작주소
- np.ndim: 데이터의 차원 타입 제공
- np.shape: 배열의 형태 제공
- np.size: 배열 요소의 총 개수

메서드 (ndarray 클래스로 사용할 수 있는 함수):
- np.array(): 배열 생성
- np.arange(): python의 range함수와 동일
- np.random.random(): 0~1의 무작위 결과를 만든다. (실행마다 무작위로 바뀜)
- np.random.seed(): 일정한 무작위 결과를 얻는다. (한번 무작위 값을 고정)
- np.random.shuffle(): 요소들을 랜덤하게 섞는다.
- np.column_stack(): 전달받은 리스트를 일렬로 세우고 나란히 연결한다. 연결할 리스트는 파이썬 튜플로 전달한다.
- np.ones() 요소가 1인 ndarray 생성
- np.zeros() 요소가 0인 ndarray 생성


아래에서 코드를 통해 확인해보도록 하자!


3. ndarray 속성 살펴보기

arr1 = np.array([10,20,30])
arr2 = np.array([[1,2,3],[4,5,6]])
print(f'arr1의 속성- 시작주소:{arr1.data} 차원:{arr1.ndim} 형태:{arr1.shape} 요소개수: {arr1.size}')
print(f'arr2의 속성- 시작주소:{arr2.data} 차원:{arr2.ndim} 형태:{arr2.shape} 요소개수: {arr2.size}')


# 출력결과:
# arr1의 속성- 시작주소:<memory at 0x7f3983d62f40> 차원:1 형태:(3,) 요소개수: 3
# arr2의 속성- 시작주소:<memory at 0x7f39883ab040> 차원:2 형태:(2, 3) 요소개수: 6


위에서 살펴보았던 ndarray의 속성, 배열의 시작주소, 차원, shpae을 출력해보았다.
arr1과 arr2의 차이는 1차원과 2차원이다.

4. Numpy 연산

4-1 파이썬의 list와 Numpy의 ndarray 연산 비교

파이썬의 list 연산

data1 = [1, 2, 3]
data2 = [10, 20, 30]
print('덧셈연산자:',data1+data2)   # 덧셈: list와 list 연결
print('곱셈연산자:',data1*3)       # 곱셈: list * 숫자만큼 반복


# 출력결과:
# 덧셈연산자: [1, 2, 3, 10, 20, 30]
# 곱셈연산자: [1, 2, 3, 1, 2, 3, 1, 2, 3]



넘파이의 ndarray 연산

arr1 = np.array([1,2,3])
arr2 = np.array([10,20,30])
arr3 = np.array([[1,2,3],[4,5,6]])
#산술연산: 넘파이는 원소들끼리 계산한다.  
print('arr1+arr2:', arr1+arr2)    
print('arr1-arr2:', arr1-arr2)
print('arr1*arr2:', arr1*arr2)
print('arr1/arr2:', arr1/arr2)
print('arr1+100:', arr1+100)
print('arr3+100:', arr3+100)

# 출력결과:
# arr1+arr2: [11 22 33]
# arr1-arr2: [ -9 -18 -27]
# arr1*arr2: [10 40 90]
# arr1/arr2: [0.1 0.1 0.1]
# arr1+100: [101 102 103]
# arr3+100: [[101 102 103] [104 105 106]]



넘파이는 Broadcasting 방식을 사용하고, 해당 인덱스 요소끼리 연산을 수행한다!
또한파이썬의 리스트 연산과 달리 배열끼리 산술연산이 가능하다.

5. ndarray 요소 접근 방법

  • 인덱싱 방법: 객체변수명[인덱스]
  • 슬라이싱 방법: 객체변수명[시작인덱스:끝인덱스+1] → 파이썬의 리스트와 비슷하다

1차원에서 요소 접근하기

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

# 인덱싱
print(arr1[3])  # 3번 인덱스의 요소 가져오기
# 여러개의 요소 가져오기: 객체변수명[[인덱스, 인덱스, ..., 인덱스]] -> 리스트를 넣는다. 
print(arr1[[0,3]])  # arr1에서 0과 3만 가져온다

# 슬라이싱 - 연속된 요소 가져오기
print(arr1[0:6:2])   #0번 인덱스부터 5번 인덱스까지 2간격으로 가져온다(6-1)
print(arr1[::2])     # 짝수요소만 가져오기.처음과 끝 인덱스는 각각 생략이 가능하다.


# 출력결과:
# 3
# [0 3]
# [0 2 4]
# [ 0 2 4 6 8 10]





2차원에서 요소 접근하기

arr2 = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])

#2차원 ndarray에서 0번 요소의 요소데이터 출력하기
print(arr2[0][0], arr2[1][1], arr2[2][2])   # [행][열]의 요소를 가져온다

#2차원 ndarray에서 0번 column(열), 즉 세로 데이터 추출하기
#객체변수명: [모든행인덱스, 열인덱스]
print(arr2[:,0])   #모든 행의 0번 열


# 출력결과:
# 1 5 9
# [ 1 4 7 10]

2차원 ndarray에서 행, 또는 열의 자료만 추출할 수 있다. 행 또는 열에 : 로 표시하면 해당 행 또는 열 모두를 의미한다.


6. 넘파이 통계 함수

통계함수 모음

arr2 = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])   

# ndarray 요소 전체에 대한 합계,최대, 최소, 평균, 표준편차
print('요소전체 통계:', arr2.sum(), arr2.max(), arr2.min(), arr2.mean(), arr2.std())

#행(가로데이터)에 대한 통계/집계함수 -> 0행에 대해
print('행 통계:',arr2[0].max(), arr2[0].std(), arr2[0].mean())

#열(세로데이터)에 대한 통계/집계함수 ->0열에 대해
print('열 통계:',arr2[:,0].max(), arr2[:, 0].min(), arr2[:, 0].sum())


# 출력결과:
# 요소전체 통계: 78 12 1 6.5 3.452052529534663
# 행 통계 3 0.816496580927726 2.0
# 열 통계 10 1 22


합계, 최대, 최소, 평균, 표준편차에 대한 통계함수를 제공한다. 인덱싱을 이용해 특정 행, 특정 열에 대한 통계를 따로 낼 수 있다.


axis를 이용한 열별, 행별 통계

print(arr2)
#ndarray객체에서 열(column, 세로 데이터 데이터 통계, 집계함수 -> 세로로!! 
print('각 열 합계: ', arr2.sum(axis=0),'각 열 최대: ',arr2.max(axis=0),'각 열 최소: ',arr2.min(axis=0))

#ndarray객체에서 행(row), 가로 데이터 데이터 통계, 집계함수 -> 가로로!!
print('각 행 합계: ',arr2.sum(axis=1), '각 행 최대: ', arr2.max(axis=1), '각 행 최소: ', arr2.min(axis=1))


# 출력결과:
[[ 1 2 3]
 [ 4 5 6]
 [ 7 8 9]
 [10 11 12]]
# 각 열 합계: [22 26 30] 각 열 최대: [10 11 12] 각 열 최소: [1 2 3]
# 각 행 합계: [ 6 15 24 33] 각 행 최대: [ 3 6 9 12] 각 행 최소: [ 1 4 7 10]



axis를 이용해 열별로, 행별로 통계를 낼 수 있다. (concatenate함수와 axis 방향이 다르다)
axis = 0이면 세로, 열별로, axis = 1이면 가로, 행별로 통계를 낸다.