[빅데이터분석기사 실기] 제1유형: 데이터 전처리
1. 데이터 탐색¶
1) 데이터 불러오기
In [1]:
import numpy as np # 넘파이 패키지 임포트
import pandas as pd # 판다스 패키지 임포트
import matplotlib.pyplot as plt # matplotlib 패키지 임포트
# 깃허브에 있는 csv 파일 읽어와서 데이터프레임 df로 넣기 - 타이타닉 데이터셋
df = pd.read_csv("https://raw.githubusercontent.com/suetudy/BigDataAnalysisEngineer_Certification/main/Titanic.csv")
In [2]:
# 데이터프레임 전체 출력
df
Out[2]:
PassengerId | Survived | Pclass | Name | Gender | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
886 | 887 | 0 | 2 | Montvila, Rev. Juozas | male | 27.0 | 0 | 0 | 211536 | 13.0000 | NaN | S |
887 | 888 | 1 | 1 | Graham, Miss. Margaret Edith | female | 19.0 | 0 | 0 | 112053 | 30.0000 | B42 | S |
888 | 889 | 0 | 3 | Johnston, Miss. Catherine Helen "Carrie" | female | NaN | 1 | 2 | W./C. 6607 | 23.4500 | NaN | S |
889 | 890 | 1 | 1 | Behr, Mr. Karl Howell | male | 26.0 | 0 | 0 | 111369 | 30.0000 | C148 | C |
890 | 891 | 0 | 3 | Dooley, Mr. Patrick | male | 32.0 | 0 | 0 | 370376 | 7.7500 | NaN | Q |
891 rows × 12 columns
2) 데이터 탐색
In [3]:
# 데이터셋의 앞부분 확인
df.head()
Out[3]:
PassengerId | Survived | Pclass | Name | Gender | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
In [4]:
# 데이터셋 뒷부분 확인
df.tail()
Out[4]:
PassengerId | Survived | Pclass | Name | Gender | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
886 | 887 | 0 | 2 | Montvila, Rev. Juozas | male | 27.0 | 0 | 0 | 211536 | 13.00 | NaN | S |
887 | 888 | 1 | 1 | Graham, Miss. Margaret Edith | female | 19.0 | 0 | 0 | 112053 | 30.00 | B42 | S |
888 | 889 | 0 | 3 | Johnston, Miss. Catherine Helen "Carrie" | female | NaN | 1 | 2 | W./C. 6607 | 23.45 | NaN | S |
889 | 890 | 1 | 1 | Behr, Mr. Karl Howell | male | 26.0 | 0 | 0 | 111369 | 30.00 | C148 | C |
890 | 891 | 0 | 3 | Dooley, Mr. Patrick | male | 32.0 | 0 | 0 | 370376 | 7.75 | NaN | Q |
In [5]:
# 데이터셋 구조와 특징
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 891 entries, 0 to 890 Data columns (total 12 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 PassengerId 891 non-null int64 1 Survived 891 non-null int64 2 Pclass 891 non-null int64 3 Name 891 non-null object 4 Gender 891 non-null object 5 Age 714 non-null float64 6 SibSp 891 non-null int64 7 Parch 891 non-null int64 8 Ticket 891 non-null object 9 Fare 891 non-null float64 10 Cabin 204 non-null object 11 Embarked 889 non-null object dtypes: float64(2), int64(5), object(5) memory usage: 83.7+ KB
In [6]:
# 데이터프레임의 기술통계(기초통계량)
df.describe(include='all')
Out[6]:
PassengerId | Survived | Pclass | Name | Gender | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 891.000000 | 891.000000 | 891.000000 | 891 | 891 | 714.000000 | 891.000000 | 891.000000 | 891 | 891.000000 | 204 | 889 |
unique | NaN | NaN | NaN | 891 | 2 | NaN | NaN | NaN | 681 | NaN | 147 | 3 |
top | NaN | NaN | NaN | Braund, Mr. Owen Harris | male | NaN | NaN | NaN | 347082 | NaN | B96 B98 | S |
freq | NaN | NaN | NaN | 1 | 577 | NaN | NaN | NaN | 7 | NaN | 4 | 644 |
mean | 446.000000 | 0.383838 | 2.308642 | NaN | NaN | 29.699118 | 0.523008 | 0.381594 | NaN | 32.204208 | NaN | NaN |
std | 257.353842 | 0.486592 | 0.836071 | NaN | NaN | 14.526497 | 1.102743 | 0.806057 | NaN | 49.693429 | NaN | NaN |
min | 1.000000 | 0.000000 | 1.000000 | NaN | NaN | 0.420000 | 0.000000 | 0.000000 | NaN | 0.000000 | NaN | NaN |
25% | 223.500000 | 0.000000 | 2.000000 | NaN | NaN | 20.125000 | 0.000000 | 0.000000 | NaN | 7.910400 | NaN | NaN |
50% | 446.000000 | 0.000000 | 3.000000 | NaN | NaN | 28.000000 | 0.000000 | 0.000000 | NaN | 14.454200 | NaN | NaN |
75% | 668.500000 | 1.000000 | 3.000000 | NaN | NaN | 38.000000 | 1.000000 | 0.000000 | NaN | 31.000000 | NaN | NaN |
max | 891.000000 | 1.000000 | 3.000000 | NaN | NaN | 80.000000 | 8.000000 | 6.000000 | NaN | 512.329200 | NaN | NaN |
3) 변수 타입 변환
In [7]:
# Survived, Pclass의 형태는 숫자(int64)이지만 범주형 변수이므로 astype() 함수를 사용해 변수의 타입 변환
df["Survived"] = df["Survived"].astype(str)
df["Pclass"] = df["Pclass"].astype(str)
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 891 entries, 0 to 890 Data columns (total 12 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 PassengerId 891 non-null int64 1 Survived 891 non-null object 2 Pclass 891 non-null object 3 Name 891 non-null object 4 Gender 891 non-null object 5 Age 714 non-null float64 6 SibSp 891 non-null int64 7 Parch 891 non-null int64 8 Ticket 891 non-null object 9 Fare 891 non-null float64 10 Cabin 204 non-null object 11 Embarked 889 non-null object dtypes: float64(2), int64(3), object(7) memory usage: 83.7+ KB
4) 기초 데이터 분석
- Pclass(등급) 변수 분석
In [8]:
# Pclass 빈도수 구하기
# groupby(): Pcalss별로 그룹핑
# size(): 크기 확인
grouped = df.groupby("Pclass")
grouped.size()
Out[8]:
Pclass 1 216 2 184 3 491 dtype: int64
- Fare(요금) 변수 분석
In [9]:
# Histogram
plt.hist(df["Fare"])
plt.show()
# 데이터 분리
data_0 = df[df["Survived"]=="0"]["Fare"] # 사망자의 요금 데이터
data_1 = df[df["Survived"]=="1"]["Fare"] # 생존자의 요금 데이터
# Boxplot - Survived 값에 따른 Fare 값의 분포를 보여준다.
fig, ax = plt.subplots()
ax.boxplot([data_0, data_1])
plt.show()
- Gender 변수 분석
In [10]:
# 빈도 수 계산
grouped = df.groupby("Gender")
print(grouped.size())
Gender female 314 male 577 dtype: int64
In [11]:
# 성별 생존자 수
data_0 = df[df["Gender"]=="female"]["Survived"] # 여성의 생존 데이터
grouped = pd.DataFrame(data_0).groupby("Survived")
print(grouped.size())
Survived 0 81 1 233 dtype: int64
In [12]:
data_0 = df[df["Gender"]=="male"]["Survived"] # 남성의 생존 데이터
grouped = pd.DataFrame(data_0).groupby("Survived")
print(grouped.size())
Survived 0 468 1 109 dtype: int64
2. 데이터 전처리¶
데이터 변환¶
1) 표준 정규화
스케일링(scaling): 데이터의 범위가 같아지도록 변수별로 값을 비례적으로 조정하는 과정
- Z-표준화
In [13]:
# 방법1. numpy > z = (x - np.mean(x)) / np.std(x)
z_scaled_1 = (df['Fare'] - np.mean(df['Fare'])) / np.std(df['Fare'])
In [14]:
# 방법2. scipy.stats > zscore()
import scipy.stats as ss
z_scaled_2 = ss.zscore(df['Fare'])
In [15]:
# 방법3. sklearn.preprocessing > StandardScaler().fit_transform()
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
z_scaled_3 = scaler.fit_transform(df[['Fare']])
- Min-Max 정규화
In [16]:
# 방법1. numpy > min_max = (x - np.min(x)) / (np.max(x) - np.min(x))
fare_min = np.min(df['Fare'])
fare_max = np.max(df['Fare'])
min_max_scaled_1 = (df['Fare'] - fare_min)/(fare_max - fare_min)
In [17]:
# 방법2. sklearn.preprocessing > MinMaxScaler().fit_transform()
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
min_max_scaled_2 = scaler.fit_transform(df[['Fare']])
2) 정규분포변환
In [18]:
# Boston House Price 데이터셋 불러오기
df1 = pd.read_csv("https://raw.githubusercontent.com/suetudy/BigDataAnalysisEngineer_Certification/main/boston.csv")
- log() 변환
In [19]:
# 왜도 계산
import scipy.stats as ss
print(ss.skew(df1['CRIM']))
5.207652387859715
In [20]:
# 양수: log(x)
# 음수: log(max(x+1)-x)
df1['CRIM1'] = np.log(df1['CRIM'])
print(ss.skew(df1['CRIM1']))
0.40473014342603986
- log10() 변환
In [21]:
# 양수: log10(x)
# 음수: log10(max(x+1)-x)
df1['CRIM2'] = np.log10(df1['CRIM'])
print(ss.skew(df1['CRIM2']))
0.4047301434260401
3) 범주화, 이산형화
연속형 변수를 범주형 변수로 변환
- 조건을 사용해서 구간을 직접 지정
In [22]:
df['Age_Range1'] = 0
df.loc[(df['Age']<7), 'Age_Range1'] = 'Babyhood'
df.loc[((df['Age']>=7) & (df['Age']<19)), 'Age_Range1'] = 'Adolescence'
df.loc[((df['Age']>=19) & (df['Age']<64)), 'Age_Range1'] = 'Adult'
df.loc[(df['Age']>=64), 'Age_Range1'] = 'OldMan'
- cut() 함수 사용
In [23]:
df['Age_Range2'] = pd.cut(x=df['Age'],
bins=[0,7,19,64,80],
labels=['Babyhood', 'Adolescence', 'Adult', 'OldMan'],
include_lowest=True)
- qcut() 함수 사용
In [24]:
df['Age_Range3'] = pd.qcut(x=df['Age'], q=4, labels=['Babyhood', 'Adolescence', 'Adult', 'OldMan'])
차원축소: PCA(주성분분석)¶
In [25]:
# Iris 데이터셋 불러오기
df2 = pd.read_csv("https://raw.githubusercontent.com/suetudy/BigDataAnalysisEngineer_Certification/main/Iris.csv")
1) PCA 분석
In [26]:
# 연속형 변수와 범주형 변수 분리
df3 = df2.drop(['Species', 'Id'], axis=1)
# 변수 표준화
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df3 = scaler.fit_transform(df3)
In [27]:
# PCA 수행
from sklearn.decomposition import PCA
pca = PCA(n_components=2) # 주성분을 몇개로 할지 결정
p_score = pca.fit_transform(df3)
print(p_score.shape)
print(pca.explained_variance_ratio_)
(150, 2) [0.72770452 0.23030523]
결측치 처리¶
In [28]:
df = pd.read_csv("https://raw.githubusercontent.com/suetudy/BigDataAnalysisEngineer_Certification/main/Titanic.csv")
1) 결측치 확인
In [29]:
# info() 함수로 컬럼별 결측값 개수 확인
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 891 entries, 0 to 890 Data columns (total 12 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 PassengerId 891 non-null int64 1 Survived 891 non-null int64 2 Pclass 891 non-null int64 3 Name 891 non-null object 4 Gender 891 non-null object 5 Age 714 non-null float64 6 SibSp 891 non-null int64 7 Parch 891 non-null int64 8 Ticket 891 non-null object 9 Fare 891 non-null float64 10 Cabin 204 non-null object 11 Embarked 889 non-null object dtypes: float64(2), int64(5), object(5) memory usage: 83.7+ KB
In [30]:
# isnull() 함수로 결측치 찾고, sum() 함수로 결측치 개수 파악
print(df.isnull().sum())
PassengerId 0 Survived 0 Pclass 0 Name 0 Gender 0 Age 177 SibSp 0 Parch 0 Ticket 0 Fare 0 Cabin 687 Embarked 2 dtype: int64
2) 결측치 대체
- 결측치가 있는 행 전체를 데이터셋에서 제거
In [31]:
# 결측치가 있는 모든 행 제거
df_1 = df.dropna(axis=0)
print(df_1.isnull().sum())
print(df.shape, df_1.shape)
PassengerId 0 Survived 0 Pclass 0 Name 0 Gender 0 Age 0 SibSp 0 Parch 0 Ticket 0 Fare 0 Cabin 0 Embarked 0 dtype: int64 (891, 12) (183, 12)
- 결측치를 지정값으로대체
In [32]:
# 결측치를 평균값으로 대체
age_mean = df['Age'].mean()
df['Age'].fillna(age_mean, inplace=True)
print(df['Age'].isnull().sum())
0
In [33]:
# 결측치를 최빈값으로 대체
from scipy.stats import mode
embarked_mode = df['Embarked'].mode()
df['Embarked'].fillna(embarked_mode[0], inplace=True)
print(df['Embarked'].isnull().sum())
0
- 결측치를 인접한 값으로 대체
In [34]:
df['Embarked'].fillna(method='ffill', inplace=True)
- 결측치를 그룹별 평균값으로 대체
In [35]:
# 성별에 따른 평균 나이
print(df.groupby('Gender')['Age'].mean())
Gender female 28.216730 male 30.505824 Name: Age, dtype: float64
- 결측치를 보간법으로 채우기
In [36]:
df['Age'] = df['Age'].interpolate(method='linear')
이상치(Outlier) 처리¶
1) 이상치 확인
In [37]:
# boxplot 그림으로이상치 확인
plt.boxplot(df['Fare'])
plt.show()
2) IQR(사분위범위) 구하기
In [38]:
# quantile() 함수로 사분위 범위 확인
Q1 = df['Fare'].quantile(.25)
Q2 = df['Fare'].quantile(.5)
Q3 = df['Fare'].quantile(.75)
IQR = Q3 - Q1
print(Q1, Q2, Q3)
print(IQR)
7.9104 14.4542 31.0 23.0896
In [39]:
# describe() 함수로 사분위 범위 확인
Q1 = df['Fare'].describe()['25%']
Q2 = df['Fare'].describe()['50%']
Q3 = df['Fare'].describe()['75%']
IQR = Q3 - Q1
print(Q1, Q2, Q3)
print(IQR)
7.9104 14.4542 31.0 23.0896
3) IQR 사용해서 이상치 제거
이상치
Outlier > Q3 + IQR * 1.5
Outlier < Q1 - IQR * 1.5
In [40]:
upperOulier = df[df['Fare'] > (Q3 + IQR * 1.5)].index
lowerOulier = df[df['Fare'] < (Q1 - IQR * 1.5)].index
df.drop(upperOulier, inplace=True)
df.drop(lowerOulier, inplace=True)
plt.boxplot(df['Fare'])
plt.show()
평활화¶
In [41]:
df4 = pd.read_csv("https://raw.githubusercontent.com/suetudy/BigDataAnalysisEngineer_Certification/main/AirPassengers.csv")
1) 단순이동평균
In [42]:
# 10년 단순이동평균
df4['sma'] = df4['#Passengers'].rolling(10).mean()
plt.plot(df4['#Passengers'])
plt.plot(df4['sma'])
plt.show()
2) 지수가중이동평균
In [43]:
# 10년 지수가이동평균
df4['ewm'] = df4['#Passengers'].ewm(10).mean()
plt.plot(df4['#Passengers'])
plt.plot(df4['ewm'])
plt.show()
'자격증 > 빅데이터분석기사' 카테고리의 다른 글
[빅데이터분석기사 실기] train, test 데이터의 범주가 서로 다른 경우 (0) | 2024.06.15 |
---|---|
[빅데이터분석기사 실기] 총 정리 - 깃허브 (0) | 2024.05.28 |
[빅데이터분석기사 실기] 제3유형: 통계적 가설검정(2) (0) | 2024.05.28 |
[빅데이터분석기사 실기] 제3유형: 통계적 가설검정(1) (0) | 2024.05.25 |
[빅데이터분석기사 실기] 제2유형: 데이터 분석 (0) | 2024.05.22 |