여유로움
[11.27 토] 빅데이터 분석기사 실기 - Pandas (30~35강) 본문
1. 통계 분석 개요
|
# [1] 평균, 분산, 표준편차 구하기
# Delta Degrees of Freedom (ddof=1) : pandas - 표본이 기준, 모분산/모표준편차는 ddof=0으로 주어야 함
s = pd.Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print('표본평균:', s.mean())
print('표본분산:', s.var())
print('표본표준편차:', s.std())
print('모분산:', s.var(ddof=0))
print('모표준편차:', s.std(ddof=0))
|
# [2] numpy의 var()와 pandas의 var()가 다른 이유는?
# ddof=0, numpy - 모집단
s = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print('평균:', s.mean())
print('표본분산:', s.var(ddof=1))
print('표본표준편차:', s.std(ddof=1))
print('모분산:', s.var())
print('모표준편차:', s.std())
|
2. 표본추출(Sampling)
|
# [1] tips 데이터를 가져오기 한다
tips = sns.load_dataset("tips")
tips.head(3)
# [2] 단순 무작위 추출 - 비율 사용
# 0.02(2%) 추출 : 244 * 0.02 = 4.88 -> 5개
tips.sample(frac=0.02, random_state=1)
# [3] 단순 무작위 추출 - 정수 사용
# 5개 sample 추출
tips.sample(n=5, random_state=1)
# [4] 계통 추출 - 1부터 시작해 50 마다 1개 추출
# tips의 iloc을 사용해 특정 번호 list => [1, 51, 101, 151, 201] 로 indexing
tips.iloc[range(1, len(tips), 50),:]
# [5] 층화 추출 - 성별을 기준으로 성별 비율에 맞춰 10개 데이터 추출
# [5-1] 성별 비율 구하기(rate), 추출할 sample 개수 구하기(sample_n)
sample_n = 10
temp = tips['sex'].value_counts(normalize=True).to_frame()
temp.columns = ['rate']
temp['sample_n'] = round(sample_n * temp['rate'], 0).astype('int')
temp
# [5-2] Female, Male로 데이터 분리 및 sample개수 만큼의 임의 표본 추출
Female = tips.loc[tips['sex'] == 'Female', :]
Male = tips.loc[tips['sex'] == 'Male', :]
df1 = Female.sample(n=temp.loc['Female', 'sample_n'], random_state=1)
df2 = Male.sample(n=temp.loc['Male', 'sample_n'], random_state=1)
df = df1.append(df2) # pd.concat([df1, df2])
df = df.sample(frac=1, random_state=123) #전체 데이터를 섞을 때 사용
df
|
3. 이상치
|
# [1] 이상치와 평균, 중앙값의 관계
import pandas as pd
data1 = [10,20,30,40,50]
data2 = [10,20,30,40,200]
a = pd.Series(data1)
b = pd.Series(data2)
print('평균 ', a.mean(), b.mean())
print('중앙값', a.median(), b.median())
# [2] seaborn의 tips 데이터셋 가져오기
tips = sns.load_dataset("tips")
# [3] tips의 'total_bill'의 이상치를 그래프로 확인하기
tips['total_bill'].plot.box(figsize=(3,4))
plt.show()
# [4] DataFrame의 plot을 사용하여 연속형 데이터에 대해 모두 boxplot 그리기
tips.plot(kind='box', subplots=True, figsize=(9,4))
plt.show()
# [5] ESD(Extream Studentized Diviate)를 이용한 방법
# 평균으로 부터 3 표준편차 떨어진 값을 이상치로 판단
# tip에 대한 이상치 구하기, 소수점 아래 2째자리까지 표기
s = tips['tip']
s_mean, s_std = s.mean(), s.std()
e_lower = round(s_mean - 3 * s_std, 2) #평균-3*표준편차
e_upper = round(s_mean + 3 * s_std, 2) #평균+3*표준편차
print(f'Lower: {e_lower}, Upper: {e_upper}')
s = tips['tip']
s_mean, s_std = s.mean(), s.std()
e_lower = round(s_mean-3*s_std, 2)
e_upper = round(s_mean+3*std,2)
print(f'Lower: {e_lower}, Uppser:{e_upper}')
# [6] 사분위수를 이용한 방법
# Q1 - 1.5*IQR 미만, Q3 + 1.5*IQR 초과 를 이상치로 판단 (IQR = Q3 - Q1)
# tip에 대한 이상치 구하기, 소수점 아래 2째자리까지 표기
s = tips['tip']
Q1, Q3 = s.quantile([0.25, 0.75])
IQR = Q3 - Q1
q_lower = Q1 - 1.5 * IQR
q_upper = Q3 + 1.5 * IQR
print(f'Lower: {q_lower}, Upper: {q_upper}')
|
4. 이상치 처리
# [7] 이상치 제거 - 정상범주에 있는 데이터를 indexing 하는 방법으로 처리 (q_lower, q_upper 사이값이 정상)
tips2 = tips[(tips['tip'] > q_lower) & (tips['tip'] < q_upper)] #q_lower보다 크고, q_upper보다 작은 데이터
print(tips.shape, tips2.shape)
# [8] 이상치 데이터 모음
tips_outlier = tips[(tips['tip'] <= q_lower) | (tips['tip'] >= q_upper)]
tips_outlier
# [9] 이상값 대체
# q_upper 보다 큰 데이터는 q_upper, q_lower 보다 작은 데이터는 q_lower로 변경
# tips3 데이터프레임에서 'tip' 값이 q_upper 보다 큰 것의 'tip'값을 q_upper 값으로 변경
# tips3 데이터프레임에서 'tip' 값이 q_lower 보다 작은 것의 'tip'값을 q_lower 값으로 변경
tips3 = tips.copy()
# code here
tips3.loc[tips3['tip'] > q_upper, 'tip'] = q_upper
tips3.loc[tips3['tip'] < q_lower, 'tip'] = q_lower
tips3.loc[(tips3['tip'] > q_upper) | (tips3['tip'] < q_lower)]
tips3['tip'].plot.box()
plt.show()
|
5. 데이터 변환(Transform)
|
# [0] 데이터 가져오기
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
tips = sns.load_dataset("tips")
# [1] tips에서 tip의 분포 확인
s = tips['tip']
s.plot.hist(bins=20)
plt.show() #오른쪽으로 꼬리가 길 때 => log, sqrt 함수 이용
# [5] tip의 분포를 오른쪽 꼬리가 긴 것에 대해서 짧게 만들기 (로그)
s = np.log1p(tips['tip']) #데이터가 0을 포함하고 있을 것 같을 때 log1p 사용
s.plot.hist(bins=20)
plt.show()
# [6] tip의 분포를 오른쪽 꼬리가 긴 것에 대해서 짧게 만들기 (제곱근)
s = np.sqrt(tips['tip'])
s.plot.hist(bins=20)
plt.show()
# [7] tips['tip'] 원본 -> log1p -> expm1 = 원본
a = tips['tip']
b = np.log1p(a)
c = np.expm1(b)
print(a[:3], b[:3], c[:3], sep='\n\n')
|
6. 데이터 스케일링(Scaling)
|
# [1] Scaling을 위한 함수 구현
def minmaxScale(x):
return (x - x.min()) / (x.max() - x.min())
def standardScale(x):
return (x - x.mean()) / x.std()
# [2-1] minmaxScale 함수를 사용한 'tip' 컬럼의 스케일링
x = minmaxScale(tips['tip'])
print(x.min(), x.max())
# [2-2] standardScale 함수를 사용한 'tip' 컬럼의 스케일링
x = standardScale(tips['tip'])
print(x.mean(), x.std())
# [3] sklearn 라이브러리의 스케일러(MinMaxScaler)를 사용한 스케일링
# 스케일러의 fit_transform() 사용시 2차원의 데이터를 전달해야 함
# (DataFrame도 2차원), 결과는 ndarray로 반환 됨
from sklearn.preprocessing import MinMaxScaler, StandardScaler
x = MinMaxScaler().fit_transform(tips[['tip']])
print(x.min(), x.max())
# [5] sklearn 라이브러리의 스케일러(StandardScaler)를 사용한 스케일링
from sklearn.preprocessing import StandardScaler
x = StandardScaler().fit_transform(tips[['tip']])
print(x.mean(), x.std())
# [6] scipy.stats의 zscore 함수를 사용한 스케일링
from scipy.stats import zscore
x = zscore(tips['tip'])
print(x.mean(), x.std())
|
7. Encoding(범주형->수치형)
|
import pandas as pd
df = pd.DataFrame({'A':['월', '화', '수', '화', '수', '금', '월'],
'B':['여자', '남자', '여자', '남자', '아이', '남자', '아이']})
# [1] 요일에 대해서 Label Encoding 합니다. (cat.codes 사용)
weekdays = '월 화 수 목 금 토 일'.split()
#print(weekdays)
df['A_LE'] = pd.Categorical(df['A'], weekdays, ordered=True)
df['A_LE'] = df['A_LE'].cat.codes
# [2] '남자', '여자', '아이'에 대해서 Label Encoding 합니다 (replace 사용)
#df['B'].replace(['남자', '여자', '아이'], [0, 1, 2]) #dictionary나 list 사용 가능
v = df['B'].unique() #어떤 범주가 있는 지 저장
df['B_LE'] = df['B'].replace(v, range(len(v)))
# [3] df의 'A' 컬럼을 One Hot Encoding 합니다.
a = pd.get_dummies(df['A'])
# [6] df의 모든 범주형 변수를 OneHotEncoding 합니다
df3 = pd.get_dummies(df)
|
8. Binning (수치형->범주형)
|
# [0] 데이터 준비
data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
df = pd.DataFrame(data, columns=['data'])
df['data'].to_list()
# [1] data를 사용하여 0~3, 4~6, 7~10 에 대한 binning을 하여 보도록 한다
# 범주의 레이블은 ['A', 'B', 'C']를 사용한다
# (Min-1, 3], (3, 6], (6, Max] 로 범주를 만들어 result_A 컬럼으로 추가합니다.
Min, Max = df['data'].min(), df['data'].max()
df['result_A'] = pd.cut(df['data'], [Min-1, 3, 6, Max], labels=['A', 'B', 'C'], right=True)
# [Min, 3), [3, 6), [6, Max+1) 로 범주를 만들어 result_B 컬럼으로 추가합니다.
df['result_B'] = pd.cut(df['data'], [Min, 3, 6, Max+1], labels=range(3), right=False)
# [2] result_A에 대해 LabelEncoding을 하여 result_C를 컬럼으로 추가합니다.
df['result_C'] = df['result_A'].cat.codes #카테고리 타입으로 되어 있는 경우, cat.codes 바로 사용 가능
|
비율을 사용하여 구간 나누기
|
# [3] 비율을 사용하여 구간나누기
df = pd.DataFrame([0, 1, 2, 3, 10, 11, 12, 13, 20, 30, 40, 50], columns=['data'])
pd.qcut(df['data'], [0, 0.25, 0.5, 0.75, 1], labels=range(4))
# [4] 다음 데이터를 binning 하여보세요 (bins 컬럼 추가)
# 사용구간 : [10, 40), [40, 50), [50, 60), [60, 70), [70, 80), [80, 101)
# 사용레이블 : '10-40미만', '40-50미만', '50-60미만', '60-70미만', '70-80미만', '80-100'
data = [55.6, 83.3, 43.4, 58.1, 31.6, 55.6, 60.7, 64.6,
73.3, 55.6, 64.3, 52.8, 22.7, 46.3, 71.4, 53.8,
64.5, 67.9, 71.4, 80.0, 59.5, 40.5, 77.1, 58.6,
65.4, 52.4, 66.7, 91.3, 41.3, 72.1, 61.9, 78.4,
63.6, 41.0, 65.2, 81.3, 54.8, 19.6, 50.0, 53.1,
41.2, 56.5]
df = pd.DataFrame(data, columns=['data'])
df['bins'] = pd.cut(df['data'], [10, 40, 50, 60, 70, 80, 101],
labels=['10-40미만', '40-50미만', '50-60미만', '60-70미만', '70-80미만', '80-100'],
right=False)
df.head()
# [5] bins 컬럼에 대해 LabelEncoding을 하여 bin_n 컬럼을 추가합니다.
df['bin_n'] = df['bins'].cat.codes
df.head()
# [6] 다음 나이 데이터를 binning 하여보세요
bin_labels = 'Baby Child Teenager Student Young_Adult Adult Elderly'.split() # 7개 label
data = [42, 11, 40, 16, 35, 58, 1, 13, 22, 7, 62, 11, 52, 67, 42, 33, 15, 60, 36, 36]
df = pd.DataFrame(data, columns=['age'])
# (-1, 5], (5, 12], (12, 18], (18, 25], (25, 35], (35, 60], (60, df['age'].max()] 로
# 범주를 만들어 age_cat 컬럼으로 추가합니다.
Max = df['age'].max()
df['age_cat'] = pd.cut(df['age'], [-1, 5, 12, 18, 25, 35, 60, Max], labels=bin_labels, right=True)
df['age_LE'] = df['age_cat'].cat.codes
df.head()
|
출처: 유튜브 강의 EduAtoZ
'셀프스터디 > 빅데이터 분석기사' 카테고리의 다른 글
빅데이터 분석기사 실기 1유형 문제풀이 (0) | 2021.11.27 |
---|---|
[11.27 토] 빅데이터 분석기사 실기 - Machine Learning (1~4강) (0) | 2021.11.27 |
[11.24 수] 빅데이터 분석기사 실기 - Pandas (24~29강) (0) | 2021.11.24 |
[11.23 화] 빅데이터 분석기사 실기 - Pandas (21~23강) (0) | 2021.11.23 |
[11.22 월] 빅데이터 분석기사 실기 - Pandas (17~20강) (0) | 2021.11.22 |