평균, 분산, 표준편차, 중앙값 등이 있다. 우선 평균 먼저 계산해보자!
평균은 숫자들의 합을 숫자의 총 개수로 나눈 값이다. 아래는 예제 코드이다.
total = 0
count = 0
numbers = input("Enter a number : (<Enter Key> to quit)")
while numbers != "":
try:
x = float(numbers)
count += 1
total = total + x
except ValueError:
print('NOT a number! Ignored..')
numbers = input("Enter a number : (<Enter Key> to quit)")
avg = total / count
print("\n average is", avg)
/-----------------------------------------------------------/
# 출력
코드 실행
Enter a number : (<Enter Key> to quit) 1
Enter a number : (<Enter Key> to quit) 2
Enter a number : (<Enter Key> to quit) 3
Enter a number : (<Enter Key> to quit)
average is 2.0
배열은 하나의 객체에 데이터 값이 여러 개 들어있는 형태이다. 파이썬에서는 리스트로 기능을 제공한다.
X = [x1, x2, x3,....xn]
그렇다면 사용자가 입력한 데이터로 배열을 만들어보자!
# 2개 이상의 숫자를 입력받아 리스트에 저장하는 함수
def numbers():
X=[] # X에 빈 리스트를 할당합니다.
while True:
number = input("Enter a number (<Enter key> to quit)")
while number !="":
try:
x = float(number)
X.append(x) # float형으로 변환한 숫자 입력을 리스트에 추가
except ValueError:
print('>>> NOT a number! Ignored..')
number = input("Enter a number (<Enter key> to quit)")
if len(X) > 1: # 저장된 숫자가 2개 이상일 때만 리턴
return X
X=numbers()
print('X :', X)
/----------------------------------------------------------------------/
# 출력
Enter a number (<Enter key> to quit) 1
Enter a number (<Enter key> to quit) 2
Enter a number (<Enter key> to quit) 3
Enter a number (<Enter key> to quit) 4
Enter a number (<Enter key> to quit) 5
Enter a number (<Enter key> to quit)
X : [1.0, 2.0, 3.0, 4.0, 5.0]
해당 코드를 보면 변수 X에 빈 리스트를 할당하여 초기화한 후 리스트의 append 메서드를 이용해 원소를 계속 추가하는 것을 알 수 있다. 다른 언어의 배열과 달리 파이썬은 가변적인 형태를 가지고 있다. 즉, 파이썬 리스트는 동적 배열(Dynamic Array)이다.
리스트와 배열
엄밀하게 개념을 구분하자면, 선형적 데이터를 다루는 자료구조인
list와array는 서로 다르다. 아래 링크를 참고하면 차이점을 알 수 있다.
리스트와 배열의 차이
import array as arr
mylist = [1, 2, 3] # 이것은 파이썬 built-in list이다.
print(type(mylist))
mylist.append('4') # mylist의 끝에 character '4'를 추가
print(mylist)
mylist.insert(1, 5) # mylist의 두번째 자리에 5를 끼워넣는다.
print(mylist)
myarray = arr.array('i', [1, 2, 3]) # 이것은 array다. import array를 해야 쓸 수 있다.
print(type(myarray))
# 아래 라인의 주석을 풀고 실행하면 에러가 난다.
#myarray.append('4') # myarray의 끝에 character '4'를 추가
print(myarray)
myarray.insert(1, 5) # myarray의 두번째 자리에 5를 끼워넣는다.
print(myarray)
/--------------------------------------------------------------------------------/
# 출력
<class 'list'>
[1, 2, 3, '4']
[1, 5, 2, 3, '4']
<class 'array.array'>
array('i', [1, 2, 3])
array('i', [1, 5, 2, 3])
평균값을 for문을 이용해 쉽게 구현해보자!
total = 0.0
for i in range(len(X)):
total = total + X[i]
mean = total / len(X)
print('sum of X: ', total)
/------------------------/
# 출력
sum of X: 15.0
중앙값(median)은 주어진 숫자를 크기 순서대로 배치할 때 가장 중앙에 위치하는 숫자로 숫자의 개수가 홀수이냐 짝수이냐에 따라 값이 달라질 수 있다.
이걸 코드로 구현할 때 조건은 아래와 같다.
def median(nums): # nums : 리스트를 지정하는 매개변수
nums.sort() # sort()로 리스트를 순서대로 정렬
size = len(nums)
p = size // 2
if size % 2 == 0: # 리스트의 개수가 짝수일때
pr = p # 4번째 값
pl = p-1 # 3번째 값
mid= float((nums[pl]+nums[pr])/2)
else: # 리스트의 개수가 홀수일때
mid = nums[p]
return mid
print('X :', X)
median(X) # 매개변수의 값으로 X를 사용함
/------------------------------------------------------------/
# 출력
X : [1.0, 2.0, 3.0, 4.0, 5.0]
3.0
1) 평균
def means(nums):
total = 0.0
for i in range(len(nums)):
total = total + nums[i]
return total / len(nums)
means(X)
/-----------------------------/
# 출력
3.0
2) 표준편차
avg = means(X)
def std_dev(nums, avg):
texp = 0.0
for i in range(len(nums)):
texp = texp + (nums[i] - avg)**2 # 각 숫자와 평균값의 차이의 제곱을 계속 더한 후
return (texp/len(nums)) ** 0.5 # 그 총합을 숫자개수로 나눈 값의 제곱근을 리턴
std_dev(X,avg)
/-------------------------------=========------------------------------------------/
# 출력
1.4142135623730951
NumPy는 Numerical Python의 줄임말로, 과학 계산용 고성능 컴퓨팅과 데이터 분석에 필요한 파이썬 패키지이다. 기본 제공되는 패키지가 아니기 때문에 pip를 이용해 설치해야한다.
pip install numpy
파이썬의 모듈, 패키지, pip?
NumPy의 장점
NumPy를 사용하기 위해서는 ndarray 객체를 만들어야한다. ndarray 객체를 이용하면 파이썬에서 사용하는 대규모 데이터 집합을 n차원 배열로 담을 수 있다. ndarray 객체는 arange()와 array([])로 만들 수 있다.
import numpy as np
# 아래 A와 B는 결과적으로 같은 ndarray 객체를 생성
A = np.arange(5)
B = np.array([0,1,2,3,4]) # 파이썬 리스트를 numpy ndarray로 변환
# 하지만 C는 좀 다를 것이다.
C = np.array([0,1,2,3,'4'])
# D도 A, B와 같은 결과를 내겠지만, B의 방법을 권장
D = np.ndarray((5,), np.int64, np.array([0,1,2,3,4]))
print(A)
print(type(A))
print("--------------------------")
print(B)
print(type(B))
print("--------------------------")
print(C)
print(type(C))
print("--------------------------")
print(D)
print(type(D))
/------------------------------------------------------------/
# 출력
[0 1 2 3 4]
<class 'numpy.ndarray'>
--------------------------
[0 1 2 3 4]
<class 'numpy.ndarray'>
--------------------------
['0' '1' '2' '3' '4']
<class 'numpy.ndarray'>
--------------------------
[0 1 2 3 4]
<class 'numpy.ndarray'>
C의 경우 '4'가 하나 들어갔을 뿐인데 0, 1, 2, 3이 모두 문자열로 바뀌었다.
왜 문자열로 변경될까?
문자열이 정수형 타입보다 범위가 크기때문에 더 큰 범위를 갖고 있는 문자열로 변경된다.
ndarray.sizendarray.shapendarray.ndimreshape()size, shape, ndim는 각각 행렬 내 원소의 개수, 행렬의 모양, 행렬의 축(axis)의 개수를 의미한다. reshape() 메서드는 행렬의 모양을 바꿔준다. 주의할 점은 모양을 바꾸기 전후 행렬의 총 원소 개수(size)가 맞아야 한다.
A = np.arange(10).reshape(2, 5) # 길이 10의 1차원 행렬을 2X5 2차원 행렬로 바꿔봅니다.
print("행렬의 모양:", A.shape)
print("행렬의 축 개수:", A.ndim)
print("행렬 내 원소의 개수:", A.size)
/--------------------------------/
# 출력
행렬의 모양: (2, 5)
행렬의 축 개수: 2
행렬 내 원소의 개수: 10
A = np.arange(10)
print('A: ', A)
B = np.arange(10).reshape(2,5)
print('B: ', B)
C = np.arange(10).reshape(3,3) # 이 줄에서 에러가 날 것이다.
print('C: ', C)
/-------------------------------------------------------/
# 출력
A: [0 1 2 3 4 5 6 7 8 9]
B: [[0 1 2 3 4]
[5 6 7 8 9]]
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
/tmp/ipykernel_16/2976122378.py in <module>
3 B = np.arange(10).reshape(2,5)
4 print('B: ', B)
----> 5 C = np.arange(10).reshape(3,3) # 이 줄에서 에러가 날 것입니다.
6 print('C: ', C)
ValueError: cannot reshape array of size 10 into shape (3,3)
NumPy 라이브러리 내부의 자료형들은 파이썬 내장함수와 동일하다.
numpy.array.dtypetype()A= np.arange(6).reshape(2, 3)
print(A)
print(A.dtype)
print(type(A))
print("-------------------------")
B = np.array([0, 1, 2, 3, 4, 5])
print(B)
print(B.dtype)
print(type(B))
print("-------------------------")
C = np.array([0, 1, 2, 3, '4', 5])
print(C)
print(C.dtype)
print(type(C))
print("-------------------------")
D = np.array([0, 1, 2, 3, [4, 5], 6]) # 이런 ndarray도 만들어질까?
print(D)
print(D.dtype)
print(type(D))
/---------------------------------------------------------------/
# 출력
[[0 1 2]
[3 4 5]]
int64
<class 'numpy.ndarray'>
-------------------------
[0 1 2 3 4 5]
int64
<class 'numpy.ndarray'>
-------------------------
['0' '1' '2' '3' '4' '5']
<U21
<class 'numpy.ndarray'>
-------------------------
[0 1 2 3 list([4, 5]) 6]
object
<class 'numpy.ndarray'>
/tmp/ipykernel_16/130055213.py:19: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
D = np.array([0, 1, 2, 3, [4, 5], 6]) # 이런 ndarray도 만들어질까요?
D = np.array([0, 1, 2, 3, [4, 5], 6], dtype=object) # warning 메시지를 보고 이렇게 바꾸자.
print(D)
print(D.dtype)
print(type(D))
/------------------------------------------------------------------------------------/
# 출력
[0 1 2 3 list([4, 5]) 6]
object
<class 'numpy.ndarray'>
# 단위행렬
np.eye(3)
/--------/
# 출력
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
# 0 행렬
np.zeros([2,3])
/-------------/
# 출력
array([[0., 0., 0.],
[0., 0., 0.]])
# 1행렬
np.ones([3,3])
/------------/
# 출력
array([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
NumPy의 강력한 연산 기능 중 하나인 브로드캐스트(broadcast) 연산이다.
브로드캐스트
A = np.arange(9).reshape(3,3)
A
/---------------------------/
# 출력
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
# ndarray A에 2를 상수배 했을 때,
A * 2
/------/
# 출력
array([[ 0, 2, 4],
[ 6, 8, 10],
[12, 14, 16]])
# ndarray A에 2를 더했을 때,
A + 2
/------/
# 출력
array([[ 2, 3, 4],
[ 5, 6, 7],
[ 8, 9, 10]])
이렇게 ndarray와 상수, 또는 서로 크기가 다른 ndarray끼리 산술연산이 가능한 기능을 브로드캐스팅이라고 한다.
# 3 X 3 행렬의 첫번째 행을 구해보자.
A = np.arange(9).reshape(3,3)
print("A:", A)
B = A[0]
print("B:", B)
/-----------------------------/
# 출력
A: [[0 1 2]
[3 4 5]
[6 7 8]]
B: [0 1 2]
A[:-1]
/-------/
# 출력
array([[0, 1, 2],
[3, 4, 5]])


# 이 슬라이싱의 결과는
print(A[:,2:])
print("--------------")
print(A[:,1:])
print("--------------")
print(A[:,:])
print("--------------")
# 이 슬라이싱의 결과와 동일
print(A[:,-1:])
print("--------------")
print(A[:,-2:])
print("--------------")
print(A[:,-3:])
/---------------------/
# 출력
[[2]
[5]
[8]]
--------------
[[1 2]
[4 5]
[7 8]]
--------------
[[0 1 2]
[3 4 5]
[6 7 8]]
--------------
[[2]
[5]
[8]]
--------------
[[1 2]
[4 5]
[7 8]]
--------------
[[0 1 2]
[3 4 5]
[6 7 8]]
NumPy에서도 다양한 의사 난수를 지원한다.
np.random.randint()np.random.choice()np.random.permutation()np.random.normal()np.random.uniform()print(np.random.random()) # 0에서 1사이의 실수형 난수 하나를 생성
print(np.random.randint(0,10)) # 0~9 사이 1개 정수형 난수 하나를 생성
print(np.random.choice([0,1,2,3,4,5,6,7,8,9])) # 리스트에 주어진 값 중 하나를 랜덤하게 골라준다.
/-----------------------------------------------------------------------------------------/
# 출력
0.3916264789856341
1
9
# 무작위로 섞인 배열을 만들어 준다.
# 아래 2가지는 기능면에서 동일하다.
print(np.random.permutation(10))
print(np.random.permutation([0,1,2,3,4,5,6,7,8,9]))
데이터별 NumPy표현법
- 소리 데이터 : 1차원 array로 표현한다. CD음원파일의 경우, 44.1kHz의 샘플링 레이트로 -32767 ~ 32768의 정수 값을 갖는다.
- 흑백 이미지 : 이미지 사이즈의 세로X 가로 형태의 행렬(2차원 ndarray)로 나타내고, 각 원소는 픽셀별로 명도(grayscale)를 0~255 의 숫자로 환산하여 표시한다. 0은 검정, 255는 흰색이다.
- 컬러 이미지 : 이미지 사이즈의 세로 X 가로x3 형태의 3차원 행렬이다. 3은 Red, Green, Blue계열의 3 색을 의미한다.
- 자연어 : 임베딩(Embedding)이라는 과정을 거쳐 ndarray로 표현될 수 있다. 블로그의 예시에서는 71,290개의 단어가 들어있는 (문장들로 이루어진) 데이터셋이 있을때, 이를 단어별로 나누고 0 - 71,289로 넘버링했다. 이를 토큰화 과정이라고 한다. 이 토큰을 50차원의 word2vec embedding 을 통해 [batch_size, sequence_length, embedding_size]의 ndarray로 표현할 수 있다.
링크
이미지는 픽셀이라고 부르는 수많은 점으로 구성되어 있다.
Image.open()Image.sizeImage.filenameImage.crop((x0, y0, xt, yt))Image.resize((w,h))Image.save()판다스 특징
Series는 일련의 객체를 담을 수 있는, 1차원 배열과 비슷한 자료 구조이다. 따라서 배열 형태인 리스트, 튜플, 딕셔너리를 통해서 만들거나 NumPy 자료형(정수형, 실수형 등)으로도 만들 수 있다.
import pandas as pd
ser = pd.Series(['a','b','c',3])
ser
/------------------------------/
# 출력
0 a
1 b
2 c
3 3
dtype: object
DataFrame은 표(table)와 같은 자료 구조입니다. Series는 한 개의 인덱스 컬럼과 값 컬럼, 딕셔너리는 키 컬럼과 값 컬럼과 같이 2개의 컬럼만 존재하는데 비해, DataFrame은 여러 개의 컬럼을 나타낼 수 있다.
