불균형한 데이터 다루기
- 실무에서는 특정한 값을 갖는 데이터가 많은 경우가 있음
- 쇼핑몰에서 웹사이트 방문자는 구매 버튼을 거의 클릭하지 않으며 암 환자의 경우 암의 종류가 다양하지만 실제로는 상당수가 희귀한 경우
- 이 데이터를 가지고 데이터 분석을 수행하는 경우 잘못된 예측을 할 가능성이 있음
- 해결책
- 소수의 값을 갖는 데이터를 더 많이 모아야 함
- 불균형한 클래스에 잘맞는 모델 평가 지표를 사용
(정확도 -> 오차 행렬, 정밀도, 재현율, F1 점수, ROC 곡선 등) - 데이터에 가중치를 적용
사이킷런의 대부분의 분류기들은 class_weight 라는 매개변수를 이용해서 가중치를 부여 - 다운 샘플링
적은 값을 갖는 데이터의 크기와 동일하게 다수 값을 갖는 데이터의 랜덤한 부분집합을 생성 - 업 샘플링
다수 값을 갖는 데이터의 크기와 동일하게 적은 값을 갖는 데이터의 중복을 허용
앙상블 - 두가지 이상을 같이 적용 (같은것, 다른것을 적용해도 앙상블이라고 함.)
불균형한(개수가 다른 경우) 클래스의 데이터를 가지고 분석을 해야 하는 겨우
- 샘플 자체의 개수가 작을 때는 자료를 더 수집하는 것이 가장 좋은 방법
- 데이터를 수집하는 것이 가능하지 않을 때는 데이터에 가중치를 적용해서 사용 - 분류 알고리즘의 매개변수 중에서 weight가 있으면 이 매개변수가 데이터에 가중치를 적용할 수 있는 매개변수이다
- 개수가 작은 데이터의 개수를 강제로 늘리거나 개수가 많은 데이터의 개수를 줄이는 업샘플링이나 다운 샘플링을 해서 알고리즘에 적용
- 평가지표를 다양하게 선택 - 정확도 대신에 재현율이나 F1 통계량 등을 이용
import numpy as np
import pandas as pd
# %%
# 0이 10개 이고 1이 90개인 ndarray 생성
list1 = []
for i in range(0, 10, 1) :
list1.append(0)
list2 = []
for i in range(0, 90, 1) :
list2.append(1)
# %%
# 2개의 list를 가지고 하나의 array 생성
target = np.array(list1 + list2)
print(target)
# %%
# 분류 알고리즘에 위의 데이터를 이용하는 경우
# 0:10%, 1:90%
# 분류 알고리즘
from sklearn.ensemble import RandomForestClassifier
# 데이터의 비율이 현저하게 다르기 때문에 가중치 설정
weights = { 0:0.9, 1:.1 }
rfc = RandomForestClassifier(class_weight=weights)
print(rfc)
# %%
# 가중치를 직접 설정하지 않고 분류기에게 판단하도록 해주는 옵션
rfc = RandomForestClassifier(class_weight='balanced')
print(rfc)
# 샘플링 비율 조정
# np.where 는 array에서 조건에 맞는 데이터만 추출
# np.where(target==0)
# taget 행렬에서 값이 0인 데이터의 행번호를 리턴
#(행번호행렬, 자료형) 으로 결과를 리턴
# 행번호행렬만 가져오기 위해서 [0]을 추가
class0 = np.where(target==0)[0]
class1 = np.where(target==1)[0]
print(len(class0))
print(len(class1))
# 데이터의 개수 확인
# target이 1인 데이터에서 target이 0인 데이터만큼 다운 샘플링을 해서 새로운 데이터셋을 생성
# 다운샘플링에서는 비복원추출 해야됨
# class1 에서 class0의 데이터 개수만큼 비복원추출(replace)
# 비복원추출 - 나온것은 제거 , True로 설정하면 나온게 또 나옴.
downsample = np.random.choice(class1, size=len(class0), replace=False)
result = np.hstack((target[class0], target[downsample])) # hstack은 매개변수 1개라 묶어
print(result)
# 업샘플링
upsample = np.random.choice(class0, size=len(class1), replace=True)
result = np.hstack((target[class1], target[upsample])) # hstack은 매개변수 1개라 묶어
print(result)
다변량 분석에서 데이터의 상대적 크기 문제
- 다변량 분석 - 2개이상의 컬럼의 데이터를 가지고 분석
- 하나의 컬럼의 데이터는 값의 범위가 0-100 이고 다른 컬럼의 데이터는 값의 범위가 0-1 이라면 이 경우 2개의 데이터를 가지고 다변량 분석을 하게 되면 첫번째 컬럼의 영향을 받게 될 수 있다.
- 이런 경우에는 값의 범위를 일치시켜 주는것이 좋다.
- 값의 범위는 같은데 분포가 다른 경우에도 분포를 기준으로 해서 값을 조정할 필요가 있다.
- 최대값으로 나누거나 최대값-최소값을 분포모로하고 해당값-최소값을 분자로해서 값을 조정
- 이러한 값의 조정을 scailing 이라고 합니다.
- 0
1 사이나 -11 사이로 조정한다. - 더 큰값으로 가능하지만 머신러니 모델에서는 값의 크기가 커지면 정확도가 떨어진다.
- 0
1. 표준화
- 모든 값들의 표준 값을 정해서 그 값을 기준으로 차이를 구해서 비교하는 방법
1) 표준값
(데이터-평균)/표준편차
: 표준값의 평균은 50
2) 편차값
- 표준값 * 10 + 50 : 위의 숫자보다 큰 숫자로 변환
# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
import numpy as np
import pandas as pd
# 표준화
# student.csv 파일의 내용을 가져오기
# index 로 이름 설정
df = pd.read_csv('../data/student.csv', encoding='cp949', index_col='이름')
print(df)
# %%
import platform
from matplotlib import font_manager, rc
# 그래프의 한글 깨짐
if platform.system() == 'Darwin':
rc('font', family='AppleGothic')
elif platform.system() == 'Windows':
font_name = font_manager.FontProperties(
fname="c:/Windows/Fonts/malgun.ttf").get_name()
rc('font', family=font_name)
# %%
# 인덱스를 기준으로 해서 막대 그래프 그리기
df.plot(kind='bar')
# %%
# 표준값 작업
# 각 과목의 평균과 표준편차 구하기
kormean, korstd = df['국어'].mean(), df['국어'].std()
engmean, engstd = df['영어'].mean(), df['영어'].std()
matmean, matstd = df['수학'].mean(), df['수학'].std()
# %%
# 표준값 구하기 - (자신의값-평균)/표준편차
# 0.0이면 중간
# 1.0이면 상하위 15%
# 2.0이면 상하위 1.1%
df['국어표준값'] = (df['국어'] - kormean)/korstd
df['영어표준값'] = (df['영어'] - engmean)/engstd
df['수학표준값'] = (df['수학'] - matmean)/matstd
print(df[['국어표준값','영어표준값','수학표준값']])
# %%
# 표준값은 비교가 가능하기는 하지만 사람이 알아보기 힘들다.
# 표준값 * 10 + 50 을 해서 편차값을 만들어서 보고서 작성
df['국어편차값'] = (df['국어표준값']*10)+50
df['영어편차값'] = (df['영어표준값']*10)+50
df['수학편차값'] = (df['수학표준값']*10)+50
print(df[['국어편차값', '영어편차값', '수학편차값']].plot(kind='bar'))
# %%
# 최대값으로 나누어서 값을 저장 - 정규화
# (자신의값-최소값)/(최대값-최소값)으로 하기도함
df['국어정규화1'] = df['국어'] / df['국어'].max()
df['국어정규화2'] = (df['국어']-df['국어'].min()) / (df['국어'].max()-df['국어'].min())
print(df[['국어정규화1', '국어정규화2']])
2. sklearn 의 정규화
1) StandardScaler
- 평균이 0이 되고 표준편차가 1이 되도록 변환
- (벡터-평균)/표준편차
- 주로 주성분분석에서 많이 이용
- 음수가 발생함.
2) MinMaxScaler
- 최대값이 1 최소값이 0이 되도록 변환
- (벡터-최소값)/(최대값-최소값)
- 신경망에서 주로 이용
3) RobustScaler
- 중앙값이 0 IQR(4분위수)를 이용하는 방식
- (벡터-중관값)/(75%-25%)
- 앞의 방식들은 이상치에 영향을 많이 받는다.
- 데이터의 분포가 불균형이거나 이상치(outlier)가 존재하는 경우에 주로이용
4) QuantileTransformer
- 데이터를 1000개의 분위로 나눈 후 0-1 사이에 고르게 분포시키는 방식
- outlier의 영향을 적데 받기 위해서 사용
데이터의 분포 - 한쪽에 완전히 쏠려있을 때는 정규화를 하지 않는다.
outlier 확인
import platform
from matplotlib import font_manager, rc
import numpy as np
import pandas as pd
df = pd.read_csv('../data/student.csv', encoding='cp949', index_col='이름')
# 그래프의 한글 깨짐
if platform.system() == 'Darwin':
rc('font', family='AppleGothic')
elif platform.system() == 'Windows':
font_name = font_manager.FontProperties(
fname="c:/Windows/Fonts/malgun.ttf").get_name()
rc('font', family=font_name)
# sklearn 을 이용한 scailing
from sklearn import preprocessing
# StandardScaler - 평균은 0 표준편차는 1이 되도록 scailing
scaler = preprocessing.StandardScaler()
# 국어 점수만 이용하는 경우 df['국어'] 가 아니고 df[['국어']]
# 머신러닝의 데이터들은 행렬을 이용하는데 data['국어'] 로 하게 되면
# 컬럼이름이 1개라서 하나의 열로 리턴되서 1차원 데이터가 된다.
# df[['국어']] 하게되면 list를 대입했기 때문에 DataFrame 으로 리턴
result = scaler.fit_transform(df[['국어']].values)
print(result) # 표준값
print(np.mean(result)) # 평균은 0에 가까워짐
print(np.std(result)) # 표준편차는 1.0에 가까워짐
scaler = preprocessing.MinMaxScaler()
result = scaler.fit_transform(df[['국어']].values)
print(result) # 표준값
print(np.mean(result))
print(np.std(result))
scaler = preprocessing.RobustScaler()
result = scaler.fit_transform(df[['국어']].values)
print(result) # 표준값
print(np.mean(result))
print(np.std(result))
scaler = preprocessing.QuantileTransformer()
result = scaler.fit_transform(df[['국어']].values)
print(result) # 표준값
print(np.mean(result))
print(np.std(result))
정규화
- 값의 범위를 0-1 사이의 데이터로 변환
- 표준화는 일정한 범위 내로 데이터를 변환하는 것이고 정규화는 0-1 사이로 해야한다.
- Nomalizer 클래스를 이용해서 transdorm 메소드에 데이터를 대입하면 된다.
- 이 때 norm 매개변수에 옵션을 설정할 수 잇는데 l1, l2, max 등의 값을 설정할수 있다.
- max는 최대값으로 나누는 방식
- max를 이용할 때는 하나의 부호형태의 데이터야 한다 (음수일때 안됨)
- l1과 l2는 거리 계산 방식
- l1 - 맨하턴 거리를 이용하고, l2는 유클리드 거리를 이용
유클리드 거리 (알고리즘에서는 기본값으로 쓰는 경우가 많다.)
A <-> B 의 가장 짧은 거리
맨한턴 거리
중간에 장애물이 있다 하여 돌아가는 거리를 계산

# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
import platform
from matplotlib import font_manager, rc
import numpy as np
import pandas as pd
df = pd.read_csv('../data/student.csv', encoding='cp949', index_col='이름')
# 그래프의 한글 깨짐
if platform.system() == 'Darwin':
rc('font', family='AppleGothic')
elif platform.system() == 'Windows':
font_name = font_manager.FontProperties(
fname="c:/Windows/Fonts/malgun.ttf").get_name()
rc('font', family=font_name)
# %%
# 2차원 행렬을 생성
matrix = df[['국어', '영어']].values
print(matrix)
print()
matrix = np.array([[30,20], [10, 30], [30,40]])
print(matrix)
# %%
from sklearn import preprocessing
# 정규화 객체 생성 - 유클리디안 거리를 사용
norm = preprocessing.Normalizer(norm='l2')
print(norm.transform(matrix))
# %%
# 맨하턴 거리 (결과는 합치면 1)
norm = preprocessing.Normalizer(norm='l1')
print(norm.transform(matrix))
# %%
# max
norm = preprocessing.Normalizer(norm='max')
print(norm.transform(matrix))
다항과 교차항 특성
기존 데이터에 데이터들을 곱하고 제곱을 해서 데이터를 추가하는 것
특성과 타겟 사이에 비선형 관계와 존재할 때 사용하는 방식
비선형 관계는 2개의 관계가 직선의 형태가 아니고 곡선의 형태인 것
각 특성이 다른 특성에 영향을 줄 때 각 특성을 곱합 교차항을 가지고 인코딩
다변량 분석(2개 이상의 컬럼을 가지고 분석)을 할 때 2개의 컬럼사이에 상관관계가 있는 경우가 있는데 이런 경우 2개의 컬럼 모두를 가지고 분석을 하게 되며 다중공선성 문제가 발생할 수 있다.
- 어떤 컬럼의 값을 알면 다른 컬럼의 값을 예측할 수 있는 경우 발생할 수 있는 문제이다.
- 이런 경우에는 2개의 컬럼을 1개의 컬럼으로 변환하는 작업을 해야 하는데(차원축소) 이런 경우 더하거나 곱하거나 제곱해서 새로운 값을 만들어 낸다.
PloynomialFeatures 클래스를 이용하는데 몇 차항까지 생성할 것인지 degree에 설정
- 첫번째 데이터로 1을 추가할지 여부를 inclued_bias에 설정 (상수항 하나를 넣을것인가)
연산식의 순서는 get_feature_names 메소드를 이용해서 확인 가능
degree=2
[1,2] -> [1,2,1,2,4]
[4,7] -> [4,7,16,27,49]
[값, 값, 제곱, 값*값, 제곱]
# 위 코드 이어서
# %%
# 다항과 교차항을 만들어주는 객체를 생성
# degree=2 : 제곱한 것 까지 생성
ploynomial = preprocessing.PolynomialFeatures(degree=2, include_bias=False)
result = ploynomial.fit_transform(matrix)
print(result)
# %%
# degree=3 : 세제곱
ploynomial = preprocessing.PolynomialFeatures(degree=3, include_bias=False)
result = ploynomial.fit_transform(matrix)
print(result)
표준화나 정규화는 직접 하는 경우가 많지만 다항식을 만드는 것은 머신러닝 알고리즘에서 자체적으로 처리하는 경우가 많다.
특성 변환
데이터에 동일한 함수를 적용해서 다른 데이터로 직접 변환하는 것
pandas에서는 apply 메소드를 이용하고 sklearn에서는 preprocessing.FunctionTransformer 나 ColumnTransformer 클래스를 이용
FunctionTransformer 는 모든 열에 동일한 함수를 적용하고 ColumnTransformer 는 서로 다른 함수를 적용할 수 있다.
- 객체를 생성할 때 적용할 함수를 설정해서 만들고 transform 메소드에 데이터를 대입하면 된다.
# 위 코드 이어서
# 함수 적용하기
matrix = np.array([[100, 200],[300, 150]])
print(matrix)
# 100을 결합하기
def intconvert(x) :
return x +100
transformer = preprocessing.FunctionTransformer(intconvert)
result = transformer.transform(matrix)
print(result)
print(df['국어'])
print(df['국어'].apply(intconvert))
Outlier 감지
- Outlier : 이상치나 극단치, 일반적인 데이터의 범위를 넘어선 값
1. z 점수를 이용하는 방법
- 중앙값을 기준으로 표준편차가 3 또는 -3 범위의 바깥쪽에 있는 데이터를 Outlier로 간주
2. z 점수의 보정
- z 점수는 데이터가 12개 이하이면 감지를 못함
- 편차의 범위를 3.5로 늘리고 0.6745를 곱한 값
3. IQR(3사분위수 - 1사분위수) 이용
- 1사분위수(25%)보다 1.5 IQR 작은 값이나 3사분위수(75%) qhek 1.5 IQR 큰 데이터를 Outlier로 간주
import numpy as np
import pandas as pd
# array를 입력받아서 z 점수(평균의 표준편차3범위) 밖에 있는 데이터를 리턴해주는 함수
def z_score_outlier(ar) :
threshold = 3
# 평균가져오기
meandata = np.mean(ar)
stdevdata = np.std(ar)
# ar의 요소를 y에 하나씩 대입하고 앞에 수식을 적용해서 결과를 가지고 다시 list를 만드는것
z_scores = [(y-meandata) / stdevdata for y in ar]
return np.where(np.abs(z_scores) > threshold)
# 샘플 데이터 생성
featrues = np.array([
[10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 2330,
5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13,
20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10,
13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4],
[10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30,
4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -3440, 4,10, 13, 20, 5, -30,
4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30, 4,10, 13, 20, 5, -30,
4,10, 13, 20, 5, -30, 4]])
result = z_score_outlier(featrues)
print(result)
# 데이터가 적으면 출력값(참고) : (array([1]), array([5])) # 2행 6열이 이상치이다.
# 데이터가 많을때 출력값(참고) : (array([0, 1]), array([32, 64]))
# %%
# z score 보정 - 범위를 3.5배로 늘리고 표준편차 0.6875를 곱해준다.
def modify_z_score_outlier(ar) :
threshold = 3.5
# 평균가져오기
meandata = np.mean(ar)
stdevdata = np.std(ar)
z_scores = [0.6875 * (y-meandata) / stdevdata for y in ar]
return np.where(np.abs(z_scores) > threshold)
result = modify_z_score_outlier(featrues)
print(result)
# %%
# IQR 이용 : 3사분위수 - 1사분위수의 +- 1.5 배 이상 차이나면 이상치로 간주
def iqr_outlier(ar) :
# 25% 와 75% 값 찾기
q1, q3 = np.percentile(ar,[25,75])
print(q1, q3)
# IQR 값 찾기
iqr = q3 - q1
# 25% 값과 1.5 iqr 보다 작은 값 찾기
lower = q1 - iqr * 1.5
upper = q3 + iqr * 1.5
return np.where((ar > upper) | (ar < lower))
result = iqr_outlier(featrues)
print(result)
Outlier 처리
1. 제거
- 설문조사를 했는데 이상한 데이터가 입력된 것 같은 경우
- 분석 목적에 맞지 않는 데이터인 경우
- 내가 쓸려는 값하고 맞지 않는 값
- 설문조사를 했는데 100세가 있어서 제외
2. 이상한 데이터로 표현해두고 특성의 하나로 간주
- 따로 분석을 수행
3. outlier의 영향이 줄어들도록 특성을 변환
- 값의 범위를 줄임(표준화, 정규화등)
- 표준화할 때는 RobustScaler를 이용하는 것이 좋음
# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
import numpy as np
import pandas as pd
house = pd.DataFrame()
house['price'] = [100000, 200000, 150000, 100000000]
house['rooms'] = [1,2,3,100]
house['square'] = [11,23,16,3000]
print(house)
# %%
# 이상한 데이터 제거 : 방이 5개 이상 제거
print(house[house['rooms']<6])
# %%
# 이상한 데이터를 별도로 표시
# 6보다 작으면 0 아니면 1을 대입
house['outlier'] = np.where(house['rooms']<6, 0, 1)
print(house)
# %%
# 값의 범위 줄이기 - np.log는 자연로그를 계산
house['log'] = [np.log(x) for x in house['rooms']]
print(house)
시계열 데이터
- 날짜 및 시간에 관련된 데이터
1. pandas의 시계열 자료형
- datatime64 : 부등호를 이용해서 크기비교를 할 수 있고 -를 이용해서 뺄셈을 할 수 있음
- Period : 두 개의 날짜 사이의 간격을 나타내기 위한 자료형
- 시계열 자료형을 별도로 구성하는 이유는 일정한 패턴을 만들기 쉽도록 하기 위해서
2. datetime64 생성
- 문자열 데이터를 시계열로 변경 : pandas.to_datetiem() 이용
- 날짜 형식의 문자열과 format 매개변수에 날짜 형식을 대입
import pandas as pd
import numpy as np
df = pd.read_csv('../data/stock-data.csv')
print(df)
# 자료형 확인
print(df.info())
# Date 컬럼의 값을 시계열로 변경해서 추가
df['newDate'] = pd.to_datetime(df['Date'])
print(df.info())
# 위와 같은 데이터프레임에서는
# 날짜를 index로 설정하는 경우가 많다
df.set_index('newDate', inplace=True)
print(df.head())
df.drop('Date', axis=1, inplace=True)
print(df.head())
3. Period
- pandas.to_period 함수를 이용해서 datetime을 Period로 생성
- freq 옵션에 기준이 되는 기간을 설정
- freq 옵션
- D : 1일 B 휴일 제외
- W : 1주 H 1시간
- M : 1개월(월말) T 1분
- MS : 1개월(월초) S 1초
- Q : 1분기말 L 1밀리초
- QS : 1분기초 U 1마이크로초
- A : 연말 N 1나노초
- AS : 연초
- B : 휴일 제외
- H, T, S, L, U, N : 시간, 분, 초, 밀리초, 마이크로초, 나노초
import pandas as pd
# 일정한 간격을 갖는 날짜 만들기
dates = ['2017-03-01', '2017-06-01', '2019-12-02']
# 날짜로 변경
pddates = pd.to_datetime(dates)
print(pddates)
# Period로 변환
pdperiod = pddates.to_period(freq='D')
print(pdperiod,'\n')
pdperiod = pddates.to_period(freq='M')
print(pdperiod,'\n')
pdperiod = pddates.to_period(freq='Q')
print(pdperiod,'\n')
pdperiod = pddates.to_period(freq='A')
print(pdperiod,'\n')
4. date_range()
일정한 간격을 소유한 날짜 데이터의 집합을 생성
매개변수
- start : 시작 날짜
- end : 종료 날짜
- periods : 생성할 날짜 개수
- freq : 이전의 freq와 동일
- tz : 시간대 설정(‘Europe/London’, ‘Asia/Seoul’, ‘Africa/Abidjan’…)
5. 날짜 데이터에서 필요한 부분 추출하기
- dt.year, dt.month, dt.day ...
- 요일은 dt.weekday_name은 문자열로 dt.weekday 하면 숫자로 리턴(월요일이 0)
- 화면에 출력할 때는 문자열로 하고 머신러닝에서 사용할 때는 숫자로 리턴 받습니다.
import pandas as pd
import numpy as np
df = pd.read_csv('../data/stock-data.csv')
# Date 컬럼의 값을 시계열로 변경해서 추가
df['newDate'] = pd.to_datetime(df['Date'])
df['year'] = df['newDate'].dt.year
print(df['year'])
6. python에서는 날짜는 datetime 패키지의 datetime 으로 제공
- 날짜 형식의 문자열을 가지고 날짜 형식의 데이터를 생성
7. shift 함수를 이용하면 기존 날짜를 이동시키는 것이 가능
# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
import pandas as pd
import numpy as np
from datetime import datetime
dates = [datetime(2017,1,1),
datetime(2017,1,4),
datetime(2017,1,7)]
ts = pd.Series(np.random.randn(3), index=dates)
print(ts)
print(ts.shift(-1))
8. resampling
- 시계열의 빈도를 변환하는 것
- 상위 빈도의 데이터를 하위 빈도의 데이터로 변환하는 것을 다운샘플링이라고 하고 반대의 과정을 업샘플링이라고 한다.
- resampling(freq, how, fill_method, closed, label, kind)
- freq : 리샘플링 빈도(M, Q, A등)
- how : 집계함수를 지정하는 것으로 기본은 mean이고 first, last, max, median, min 등
- fill_method : 업 샘플링할 때 데이터를 채우는 옵션으로 기본은 None 인데 ffill 이나 bfill을 설정해서 이전값이나 이후값으로 채울 수 있음
- closed : 다운 샘플링을 할 때 왼쪽과 오른쪽 어느쪽을 포함시킬지 설정
- label : 다운 샘플링을 할 때 레이블을 왼쪽 또는 오른쪽을 사용할것인지 여부
import pandas as pd
import numpy as np
# 일정한 간격ㅇ로 집계
ran = pd.date_range('11/3/2020', periods=20, freq='T')
print(ran)
ts = pd.Series(np.arange(20), index=ran)
print(ts)
# 5분 단위로 합계
print(ts.resample('5T').sum())
9. 날짜 데이터가 데이터프레임에 존재하는 경우 날짜 데이터를 인덱스로 설정하면 특정 시간단위로 집계를 하는 것이 쉬워진다.
시계열 이동 시간 윈도우
- 통계적 수치를 계산 할 때 최근의 데이터에 가중치를 부여해야 한다는 개념
- 평균을 구할 때 데이터 전체의 평균을 구하는 거 보다는 최근의 데이터 몇 개의 평균을 구하는 것이 미래를 예측할 때는 더 잘 맞을 가능성이 높다.
- 이전 데이터와 최근의 데이터를 같이 사용할 거라면 최근의 데이터에 가중치를 부여하는 것이 미래를 예측할 때는 더 잘 맞을 가능성이 높다.
1. rolling 함수
- 단순 이동 평균을 계산해주는 함수
- window 매개변수에 데이터 개수를 설정하면 데이터 개수 단위로 연산을 수행
2. ewm 함수
지수 이동 평균을 계산해주는 함수
지수 이동 평균은 최근의 데이터에 가중치를 부여하는 방식의 평균
- 주식 데이터는 이 평균을 사용한다.
기간(span)을 설정하면 아래 수식으로 평균
데이터가 3개인경우
x1, x2, x3(가장최근데이터)
(1-span)을 알파라고 한다. 알파를 계산할 때는 1/span 이 span 자리에 대입x3 + (1-(1-span))*x2 + (1-(1-span))^x3 / 1+(1-알파) + (1-알파)^
에이징커브
시간에 따라 변경되는 데이터를 가지고 예측할 때는 최근의 데이터에 가중치를 부여해야 한다.
x3 : 2500 (가장최근데이터)
x2 : 2000
x1 : 2200
^ : 제곱
기간이 지날수록 반영율을 줄여나간다
x3 : 2500 # 그대로 반영
x2 : (1- 1/3) * 2000
x1 : (1- 1/3)^ * 2200
지수 이동 평균
2500 + ((1 - 1/3) * 2000) + ((1 - 1/3)^ * 2200) / 1 + (1 - 1/3) + (1 - 1/3)^
지수 이동 평균
- DataFram.ewm(span=가중치를 부여할 데이터 개수).mean()
알파 = 1/span
최근의 데이터 + (1-알파)이전데이터 + (1-알파)제곱 * 그 이전 데이터
- 최근의 데이터 반영 비율을 높이고 이전 데이터의 반영 비율을 줄여서 계산하는 방식
- 주가 데이터에 많이 사용
- 주가는 최근의 데이터의 추세를 반영하는 것이 예측의 정확성을 높여주기 때문이다.
import numpy as np
import pandas as pd
#2020년 1월 1일 부터 월 단위로 5개의 데이터를 생성
timeindex = pd.date_range('01/01/2020', periods=5, freq="M")
df=pd.DataFrame(index=timeindex)
df['price'] = [10, 20, 30, 40, 50 ]
print(df)
#span을 2로 설정해서 지수이동평균 구하기
print(df.ewm(span=2).mean())
시계열 데이터에서의 누락된 값
- 시간의 간격이 일정한 상태에서 데이터가 누락된 경우라면 제거를 하는 것보다는 패턴을 확인해서 데이터를 대입하는 것이 좋다.
DataFrame 의 interpolate 함수를 호출하면 누락된 값을 채워줍니다.
- 매개변수가 없으면 선형으로 관계를 파악해서 채줘주고 method에 quadratic 을 설정하면 비선형으로 채워줍니다.
ax + b : 일차 방정식
- 선형 : 데이터의 분포가 직선에 가까워집니다.
- spearman
ax^ + bx + c : 이차 방정식 이상
- 비선형 : 데이터의 분포가 곡선에 가까워집니다.
- fearson, kendall
머신러닝을 할 때도 회귀나 분류하기 전에 데이터의 분포를 확인해야 합니다.
데이터의 분포를 확인 할 때는 산포도(scatter)를 많이 이용합니다.
# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
import numpy as np
import pandas as pd
#2020년 1월 1일 부터 월 단위로 12개의 데이터를 생성
timeindex = pd.date_range('01/01/2020', periods=12, freq="M")
df=pd.DataFrame(index=timeindex)
# 누락된 데이터( 결측치 - None, null, np.nan) 만들기
df['price'] = [10, 20, np.NaN,30, 40, 50,np.NaN, 60, 70, 90, np.NaN, 110 ]
# 선형으로 누락된 값 채우기
print(df.interpolate())
# %%
df['price'] = [10, 20, np.NaN,303, 404, 506,np.NaN, 3033, 705, 2000, np.NaN, 1310 ]
# 비선형으로 누락된 값 채우기
# method 를 주지 않았을 때는 부자연스러운 값들이 생성됨
print(df.interpolate())
# 비선형으로 누락된 값 채우기
# method='quadratic' 를 입력하니 그렇지 않을때보다 조금은 자연스러워졌다.
print(df.interpolate(method='quadratic'))
'Language_Study > Python' 카테고리의 다른 글
[Python] 11-2.Dataframe응용과 시각화 (0) | 2021.01.19 |
---|---|
[Python] 11-1.DataFrame응용과 시각화 (0) | 2021.01.19 |
[Python] 10-1.데이터전처리 (4) | 2021.01.19 |
[Python] 9.시각화 (0) | 2021.01.19 |
[Python] 8.pandas (0) | 2021.01.19 |