빅데이터 분석 절차
2. 데이터 전처리 (EDA : 탐색적 데이터 분석)
- 컬럼명 해석.
- 변수명.
- 정의.
▷ 상위, 하위 5개의 컬럼 확인.
df_t.head(5)
df_t.tail(5)
▷ 데이터의 정보 확인.
df_t.dtypes
df_t.shape
df_t.info()
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 891 entries, 0 to 890
# Data columns (total 15 columns):
# # Column Non-Null Count Dtype
# --- ------ -------------- -----
# 0 survived 891 non-null int64
# 1 pclass 891 non-null int64
# 2 sex 891 non-null object
# 3 age 714 non-null float64
# 4 sibsp 891 non-null int64
# 5 parch 891 non-null int64
# 6 fare 891 non-null float64
# 7 embarked 889 non-null object
# 8 class 891 non-null category
# 9 who 891 non-null object
# 10 adult_male 891 non-null bool
# 11 deck 203 non-null category
# 12 embark_town 889 non-null object
# 13 alive 891 non-null object
# 14 alone 891 non-null bool
# dtypes: bool(2), category(2), float64(2), int64(4), object(5)
# memory usage: 80.7+ KB
▷ 데이터의 기본 통계 정보 확인.
describe()
df_t.describe()
생략된 정보 확인.
describe(include="all")
df_t.describe(include="all")
▷ age, fare의 분포 확인.
sns.distplot()
fig = plt.figure(figsize=(10, 5))
ax3 = fig.add_subplot(1, 2, 1)
ax4 = fig.add_subplot(1, 2, 2)
sns.distplot(df_t.age, ax=ax3)
sns.distplot(df_t.fare, ax=ax4)
▷ 범주형 데이터의 분포 확인.
sns.countplot()
fig = plt.figure(figsize=(10, 10))
ax1 = fig.add_subplot(2, 2, 1)
ax2 = fig.add_subplot(2, 2, 2)
ax3 = fig.add_subplot(2, 2, 3)
ax4 = fig.add_subplot(2, 2, 4)
sns.countplot(x = "survived", ax=ax1, palette='Set3', data=df_t)
sns.countplot(x = "pclass", ax=ax2, palette='Set3', data=df_t)
sns.countplot(x = "parch", ax=ax3, palette='Set3', data=df_t)
sns.countplot(x = "sibsp", ax=ax4, palette='Set3', data=df_t)
▷ 범주형 데이터(문자)의 분포 확인.
fig = plt.figure(figsize=(10, 10))
ax1 = fig.add_subplot(3, 2, 1)
ax2 = fig.add_subplot(3, 2, 2)
ax3 = fig.add_subplot(3, 2, 3)
ax4 = fig.add_subplot(3, 2, 4)
ax5 = fig.add_subplot(3, 2, 5)
sns.countplot(x = "sex", ax=ax1, palette='Set3', data=df_t, hue='class')
sns.countplot(x = "embarked", ax=ax2, palette='Set3', data=df_t)
sns.countplot(x = "who", ax=ax3, palette='Set3', data=df_t, hue='alive')
sns.countplot(x = "embark_town", ax=ax4, palette='Set3', data=df_t, hue='sex', dodge=False)
sns.countplot(x = "alive", ax=ax5, palette='Set3', data=df_t, hue='sex', dodge=True)
▷ 범주형 데이터(카테고리, 불리언)의 분포 확인.
fig = plt.figure(figsize=(10, 10))
ax1 = fig.add_subplot(3, 2, 1)
ax2 = fig.add_subplot(3, 2, 2)
ax3 = fig.add_subplot(3, 2, 3)
ax4 = fig.add_subplot(3, 2, 4)
sns.countplot(x = "class", ax=ax1, palette='Set3', data=df_t, hue='sex')
sns.countplot(x = "deck", ax=ax2, palette='Set3', data=df_t)
sns.countplot(x = "adult_male", ax=ax3, palette='Set1', data=df_t, hue='alive')
sns.countplot(x = "alone", ax=ax4, palette='Set3', data=df_t, hue='sex')
▷ 불필요한 변수 확인 및 제거.
- drop()
- pclass = class
- alive = survived
- embark_town = embarked
- sex와 who, adult_male과 비슷.
- alone과 sibsp, parch와 비슷.
df_t.drop(columns=['class', 'alive', 'embark_town', 'who', 'adult_male', 'alone'], inplace=True)
▷ 파생 변수 생성.
- sibsp 컬럼과 parch 컬럼을 더해 famliy 컬럼 생성
df_t['family'] = df_t.sibsp + df_t.parch
- sibsp, parch 컬럼 제거
df_t.drop(columns=['sibsp', 'parch'], inplace=True)
▷ 누락 데이터 확인.
df_t.isna().sum()
# survived 0
# pclass 0
# sex 0
# age 177
# fare 0
# embarked 2
# deck 688
# family 0
# dtype: int64
▷ 누락 데이터 처리
▶ 방법1
확률적으로 가장 많이 분포하고 있는 데이터로 채웁니다.
▷ embarked의 누락 데이터를 채웁니다.
- embarked는 문자 범주형 데이터.
df1["embarked"].value_counts(dropna=False)
# S 646
# C 168
# Q 77
# Name: embarked, dtype: int64
df1.embarked.fillna('S', inplace=True)
▷ age의 누락 데이터를 채웁니다.
- age는 연속형 숫자 데이터.
▷ 클래스별 age의 중간값을 찾는다.
df1.groupby('pclass').age.agg(['median'])
▷ 클래스와 성 별 age의 중간값을 찾는다.
df1.groupby(['pclass', 'sex']).age.agg(['median'])
▷ pclass와 sex별 age의 결측치를 채운다.
age_md = df1.groupby(['pclass', 'sex']).age.agg(['median'])
# 나이 중간값
df1.loc[(df1['sex'] == 'male') & (df1['pclass'] == 1) & (df1.age.isna()), "age"] = age_md.loc[1, 'male'][0]
df1.loc[(df1['sex'] == 'male') & (df1['pclass'] == 2) & (df1.age.isna()), "age"] = age_md.loc[2, 'male'][0]
df1.loc[(df1['sex'] == 'male') & (df1['pclass'] == 3) & (df1.age.isna()), "age"] = age_md.loc[3, 'male'][0]
df1.loc[(df1['sex'] == 'female') & (df1['pclass'] == 1) & (df1.age.isna()), "age"] = age_md.loc[1, 'female'][0]
df1.loc[(df1['sex'] == 'female') & (df1['pclass'] == 2) & (df1.age.isna()), "age"] = age_md.loc[2, 'female'][0]
df1.loc[(df1['sex'] == 'female') & (df1['pclass'] == 3) & (df1.age.isna()), "age"] = age_md.loc[3, 'female'][0]
sex_list = ['male', 'female']
pclass_list = [1, 2, 3]
a = []
for i in df1.groupby(['pclass', 'sex']).age.median() :#.loc[1, 'female']
a.append(i)
for i in range(len(sex_list)):
for j in range(len(pclass_list)):
df1.loc[(df1.sex == sex_list[i]) & (df1.pclass == pclass_list[j]) & df1.age.isna(), 'age'] = a[3 * i + j]
▷ deck컬럼은 결측치가 많기 때문에 컬럼 자체를 삭제한다.
df1.drop(columns='deck', inplace=True)
▶ 방법2
fillna()로 간단하게 변경합니다.
▷ embarked 결측치 N으로 채우기.
df2.embarked.fillna('N', inplace=True)
▷ deck 결측치 N으로 채우기.
카테고리형은 추가할 수 없기 때문에 타입을 변경해주어야 한다.
df2.deck = df2.deck.astype('O')
df2.deck.fillna("N", inplace=True)
▷ age 결측치 평균값으로 채우기.
df2.age.fillna(df2['age'].mean(), inplace=True)
▶ 탐색적 데이터 분석
생존여부와 다른 컬럼들과 연관성 파악.
▷ survived와 가장 관계성이 높은 컬럼을 찾는다.
sns.heatmap()
plt.figure(figsize=(5, 5))
sns.heatmap(df1.corr(), annot=True, cmap="coolwarm", cbar=False)
▷ 연령별 컬럼을 생성하여 조건에 맞는 데이터를 입력합니다.
df1.loc[df1.age >= 50, "age_new"] = "old"
df1.loc[(df1.age < 50) & (df1.age>=10), "age_new"] = "young"
df1.loc[df1.age < 10, "age_new"] = "baby"
▷ 그래프를 생성합니다.
fig = plt.figure(figsize=(10, 10))
ax1 = fig.add_subplot(2, 2, 1)
ax2 = fig.add_subplot(2, 2, 2)
sns.countplot(x="age_new", hue="survived", data=df1, ax=ax1)
sns.violinplot(x="sex", y="age", hue="survived", data=df1, split=True, inner="quartile", ax=ax2)
→ 결론 : 여성과 아동의 생존률이 높았고 위급 상황에서 양보가 있었을것으로 예상.
▶ 문자형 데이터를 숫자형 데이터로 변경
▷ Label Encoding 1.
▶ 데이터를 불러온다.
df_t = sns.load_dataset('titanic')
df_t.drop(columns=['class', 'alive', 'embark_town', 'who', 'adult_male', 'alone'], inplace=True)
▶ sex, embarked, deck의 변수를 숫자로 변경.
- root.1 각 변수의 유니크 항목들을 확인한 후 임의의 숫자로 변경.
# age_new 컬럼 생성.
df_t.loc[df_t.age >= 50, "age_new"] = "old"
df_t.loc[(df_t.age < 50) & (df_t.age>=10), "age_new"] = "young"
df_t.loc[df_t.age < 10, "age_new"] = "baby"
for column in ['sex', 'embarked', 'age_new'] :
datas = df_t[column].unique()
for i, d in enumerate(datas) :
df_t[column].replace(d, i, inplace=True)
▷ Label Encoding 2. (Scikit-learn)
▶ 데이터를 불러옵니다.
from sklearn.preprocessing import LabelEncoder
items = ['TESLA', '삼성', '카카오', '네이버', 'Apple', 'Benz', 'Benz', 'Apple']
lb = LabelEncoder()
▶ lb에 items의 유니크한 값을 오름차순하여 입력한다.
# items의 값의 유니크한 값이 오름차순으로 정렬된다.
lb.fit(items)
▶ 현재 lb의 숫자데이터 값을 확인한다.
labels = lb.transform(items)
print(labels)
[2 4 5 3 0 1 1 0]
▶ lb의 숫자 데이터를 확인한다.
# 숫자데이터를 문자데이터로 확인이 가능하다.
lb.inverse_transform([5])
# # array(['카카오'], dtype='<U5')
▶ lb의 현재 데이터를 확인한다.
for i, n in enumerate(lb.classes_) :
print(i, n)
▶ Label encoding.
▷ root 1.
df1_sex_encoder = LabelEncoder()
df1_embarked_encoder = LabelEncoder()
df1_agenew_encoder = LabelEncoder()
df1_sex_encoder.fit(df_t['sex'])
df1_embarked_encoder.fit(df_t['embarked'])
df1_agenew_encoder.fit(df_t['age_new'])
df_t['sex'] = df1_sex_encoder.transform(df_t['sex'])
df_t['embarked'] = df1_embarked_encoder.transform(df_t['embarked'])
df_t['age_new'] = df1_agenew_encoder.transform(df_t['age_new'])
▷ root 2.
for i in ['sex', 'embarked', 'age_new']:
globals()[f'df1_{i}_encoder'] = LabelEncoder()
globals()[f'df1_{i}_encoder'].fit(df_t[i])
df_t[i] = globals()[f'df1_{i}_encoder'].transform(df_t[i])
▶ Label Encoding VS One Hot Encoding
- One Hot Encoding의 각 컬럼의 벡터는 1이기 때문에 데이터의 사이즈의 오해를 줄일 수 있다.
▶ df_t를 one-hot encoding으로 df_t2로 추가.
df_t2 = pd.get_dummies(df_t, prefix=['sex', 'embarked', 'deck'])
▶ 정규분포 그래프 시각화
▷ root.1
from scipy.stats import norm
fig = plt.figure(figsize=(10, 10))
ax1 = fig.add_subplot(2, 2, 1)
sns.lineplot(x='age' ,y=norm.pdf(df_t['age'], loc=df_t['age'].mean(), scale=2), data=df_t2, ax=ax1)
▷ root.2
df1_fs = (df_t2 - df_t2.mean())/df_t2.std()
print('mean: ')
print(df_t2.mean())
print('std : ')
print(df1_fs.std())
fig = plt.figure(figsize=(10, 10))
for no, i in enumerate(df_t2.columns):
globals()[f'ax{no+1}'] = fig.add_subplot(3,3,no+1)
sns.distplot(df1_fs[i], ax=globals()[f'ax{no+1}'])
plt.show()
▷ 컬럼의 변수가 모두 숫자형으로 변경된 상태이므로 상관관계 다시 확인.
sns.heatmap(df_t.corr(), annot=True, cmap='coolwarm', linewidths=0.2)
'Python' 카테고리의 다른 글
[Python] Coding Test (이진수 변환) (0) | 2022.10.13 |
---|---|
[Python] 빅데이터 분석 3 : 모델 선택(Model Selection) (0) | 2022.10.11 |
[Python] 빅데이터 분석 1 : 데이터 수집(Data Collection) (0) | 2022.10.11 |
[Python] Coding Test (프린터) (0) | 2022.10.10 |
[Python] any() (0) | 2022.10.10 |