2.1 EDA 기본
키워드 : EDA, 데이터 시각화, 선그래프, 막대그래프, 파이차트, 히트맵, 산점도, 군집화, 상자 그림, isnull().sum(), info(), drop(), 머신러닝, 딥러닝, AI, 파이썬, 데이터 분석, 데이터 전처리, 데이터 수집, 데이터 모델링
01. EDA란?
EDA(Exploratory Data Analysis)란 ‘탐색적 데이터 분석’으로 벨연구소의 수학자 존 튜키가 개발한 데이터 분석 방법론입니다. 데이터를 분석하고 결과를 내는 과정에서 지속적으로 데이터에 대한 ‘탐색과 이해’를 가져야 함을 의미합니다.
EDA는 데이터 분석에 있어 중요한 초기 분석의 단계입니다. 처음 데이터를 접할 때부터 데이터를 잘 이해하고 파악한 다음 어떤 결과를 만들어 낼 지 찾아가는 과정입니다. 데이터 분석으로 최종적인 결과를 만들어내기 이전에 기본적인 ‘가설’을 가지고, 그래프 혹은 표를 통해 사전 검증을 해나가는 과정을 EDA라고 말할 수 있습니다.
02. EDA의 필요성 및 목적
EDA는 다양한 이유에서 중요한 과정입니다. EDA의 필요성과 목적은 다음과 같습니다.
-
분석에 앞서 데이터의 수집을 결정하고 데이터에 대한 이해를 높일 수 있습니다.
-
데이터를 다양한 관점에서 바라봄으로써 데이터가 가지고 있는 현상을 이해하고 잠재적인 문제를 발견할 수 있습니다.
-
-
기존의 가설을 수정하거나 새로운 가정을 설정할 수 있습니다.
-
데이터를 다양한 각도에서 살펴보는 과정을 통해 문제 정의 단계에서 발견하지 못했던 다양한 패턴을 발견할 수 있습니다.
-
-
적절한 통계도구를 제시할 수 있고 자료 수집을 위한 기반이 되기도 합니다.
-
EDA 의 최종적 목표는 데이터를 이해하는 것입니다. 데이터에 대한 깊이 있는 이해는 적절한 분석 도구와 어떤 자료를 추가적으로 수집할 것인지 결정할 수 있습니다.
-
💡 EDA의 가장 근본적인 목표이자 필요성은 데이터에 대한 이해를 높이는 것입니다.
03. EDA에 자주 사용되는 시각화 그래프
시각화를 이용한 EDA에서 자주 사용되는 일부 그래프를 소개합니다. EDA, 그 중에서도 시각화를 통한 EDA를 본격적으로 진행하기 전에 먼저 데이터를 확인해봅시다. 이번 EDA에서 활용할 데이터는 Kaggle에서 제공하는 Titanic 데이터 입니다. (데이터 출처 https://www.kaggle.com/c/titanic/data)
3.0) 데이터 준비 및 전체적인 데이터 분석
- 데이터 불러오기
Kaggle에서 제공하는 Titanic 데이터 중 train 데이터를 활용하겠습니다. (train 데이터를 기반으로 test 데이터를 예측하는 ML을 위해 제공된 데이터이기 때문에 EDA에서는 train 데이터를 활용해보겠습니다. test 데이터를 사용하셔도 사실상 상관없습니다)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv("C:\\Users\\user\\Desktop\\train.csv", encoding='ANSI') #"C:\\Users\\user\\Desktop\\train.csv" 경로 설정 부분

- 결측치 확인 및 제거
(1) EDA 시각화에서 정확한 분석을 위해 결측치를 확인해보겠습니다. Age, Cabin, Embarked 부분에서 결측치가 있음을 확인할 수 있습니다.
df.isnull().sum()

(2) 다음으로 결측치가 가장 많은 Cabin 열을 제거하겠습니다. 그리고 pd.head()를 통해 상위 5개의 행을 확인해보겠습니다.
df.drop('Cabin', axis=1, inplace=True)
df.head()
.png)
- 데이터 타입 확인
간단하게 데이터 별 타입을 확인하기 위해 info.() 를 적용해보겠습니다. 기본적으로 문자열 이외에는 정수, 실수형으로 잘 구분되어 있음을 확인할 수 있습니다.
df.info()
.png)
3.1) 선 그래프(Line Plot)
첫번째로 선 그래프(line plot) 으로 데이터를 시각화 해보겠습니다. 라이브러리는 대표적인 시각화 툴인 seaborn을 활용하였습니다.
import seaborn as sns
plt.figure(figsize=(8, 5))
sns.distplot(train['Age'], bins=25)

탑승객들의 나이 분포를 선 그래프로 확인할 수 있습니다. 주로 선 그래프는 데이터 포인트를 선으로 연결하여 시계열 데이터나 연속적인 데이터의 변화를 보여줍니다.
3.2) 막대 그래프(Bar Chart)
막대 그래프(bar chart) 를 나타내보겠습니다. 막대그래프의 경우 범주형 데이터의 값들을 막대로 표현하여 각 범주 간의 비교를 도와줍니다.
f, ax = plt.subplots(1, 1, figsize=(18, 8))
sns.countplot('Sex', hue='Survived', data=df)
ax.set_title('Sex: Survived vs Dead')
plt.show()

3.3) 파이 차트(Pie Chart)
다음으로 파이차트를 시각화해보겠습니다. 파이차트는 전체에 대한 각 범주의 비율을 원형으로 표현하여 비율을 비교할 수 있습니 다. 탑승객들의 생존율을 한 눈에 보기 위해 파이차트를 그려보겠습니다.
# 'Survived' 열의 값을 'Died'와 'Survived'로 변환
pd['Survived'] = df['Survived'].map({0: 'Died', 1: 'Survived'})
plt.figure(figsize=(6, 6)) # 파이 차트 그리기
pd['Survived'].value_counts().plot.pie(explode=[0, 0.1], autopct='%1.1f%%', shadow=True) plt.title('Survived')
plt.tight_layout()
plt.show()
.png)
0과 1을 각각 ‘died’와 ‘survived’ 로 이름을 바꾼 후 파이차트를 그린 모습입니다. 사망 비율을 빨간색으로, 생존비율을 초록색으로 나타냈습니다. 파이차트를 통해 한 눈에 비율을 확인할 수 있습니다.
3.4) 히트맵(Heatmap)
다음으로 히트맵을 그려보겠습니다. 히트맵(heatmap)은 두 개의 범주형 변수 간의 상관 관계를 색상으로 표현하여 데이터의 패턴을 확인할 수 있습니다.
# 히트맵을 그리기 위해 데이터프레임에서 상관계수 행렬을 계산
correlation_matrix =df.corr()
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', linewidths=.5)
plt.title('Correlation Heatmap of Titanic Data')
plt.show()

데이터 프레임의 열에 해당하는 요소들간의 상관관계를 히트맵으로 확인할 수 있습니다. 색깔이 진할수록 두 요소간의 높은 상관관계를 보여주고 있습니다.
3.5) 산점도(Scatter Plot)
이번엔 산점도(scatter plot)을 그려보겠습니다. 산점도는 두 개의 연속형 변수 간의 상관관계를 표현하여 데이터의 분포와 패턴을 쉽게 확인할 수 있습니다.
# lmplot 그리기
sns.lmplot(x='Fare', y='Age', data=df, hue='Survived', fit_reg=False, palette={'Died':'gray', 'Survived':'yellow'})
plt.show()

Fare에 아무런 제약없이 산점도를 그린 모습입니다. Fare의 범위가 넓어 산점도를 통해 전체 분포를 정확히 확인할 수 없음을 알 수 있습니다. 데이터가 지나치게 특정 범위에 치우쳐져 있습니다. Fare의 범위를 제한하여 다시 확인해보겠습니다.
# lmplot 그리기
sns.lmplot(x='Fare', y='Age', data=df[df.Fare < 100], hue='Survived', fit_reg=False, palette={'Died':'black', 'Survived':'skyblue'})
plt.show()# lmplot 그리기
sns.lmplot(x='Fare', y='Age', data=df, hue='Survived', fit_reg=False, palette={'Died':'black', 'Survived':'skyblue'})
plt.show()

Fare의 범위를 100 미만으로 제한하여 나타낸 산점도입니다. Fare와 Age간의 상관관계와 더불어 생존과 사망의 분포까지 확인할 수 있습니다.
3.6) 군집화(Cluster Plot)
다음은 군집화 그래프 입니다. 군집 분석 결과를 시각화하여 군집 간의 유사성과 차이를 확인할 수 있습니다.
💡 군집분석이란 ?
균일한 하부 그룹에서 여러 개체들을 그들의 상호 유사성이나 계층 관계 등에 기초하여 배열하는 것을 의미합니다.
즉, 군집화(Cluster Plot) 그 래프를 그리는 것은 어떤 특성을 기반으로 군집을 형성하고 이를 시각화하는 것입니다. 군집화는 비슷한 특성을 가진 데이터들을 같은 그룹으로 묶는 작업이므로, 데이터의 특성에 따라 다양한 방식으로 군집화를 시도할 수 있습니다. 군집화 혹은 군집분석에는 다양한 종류가 있습니다. 대표적인 군집 기법으로는 K-means, 계층적 군집화, 유사도 전파 군집화 등이 있으며 이번 EDA에서는 K-means 기법을 사용하겠습니다.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.preprocessing impor# AGE와 FARE 열을 선택하여 데이터프레임 생성
# AGE와 FARE 열을 선택하여 데이터프레임 생성
data_for_clustering = df[['Age', 'Fare']].loc[df['Fare'] <= 100].dropna()
# 데이터 표준화 (Standard Scaling) scaler = StandardScaler() scaled_data = scaler.fit_transform(data_for_clustering)
# K-means 군집화 num_clusters = 3 # 군집 개수 설정
kmeans = KMeans(n_clusters=num_clusters, random_state=42)
kmeans.fit(scaled_data)
# 군집 결과를 데이터프레임에 추가 data_for_clustering['Cluster'] = kmeans.labels_
# 군집별 데이터 시각화 plt.figure(figsize=(10, 6)) for cluster_num in range(num_clusters): cluster_data = data_for_clustering[data_for_clustering['Cluster'] == cluster_num] plt.scatter(cluster_data['Age'], cluster_data['Fare'], label=f'Cluster {cluster_num + 1}')
plt.xlabel('Age')
plt.ylabel('Fare')
plt.title('K-means Clustering of Age and Fare')
plt.legend()
plt.show()

세 개의 그룹으로 군집화되었음을 확인할 수 있습니다.
-
1번 그룹(노랑색) : Age가 어리고 Fare가 낮은 그룹
-
2번 그룹(파랑색) : Age가 중간이고 높은 Fare를 가진 그룹
-
3번 그룹(빨강색) : Age가 높고 낮은 Fare를 가진 그룹
해당 그래프를 통해 나이와 요금을 기반으로 승객들을 군집화할 수 있습니다. 연령대별 혹은 가격대별 형성된 군집을 확인할 수 있습니다. (’Fare’ 의 경우 raw data를 사용하면 군집화를 쉽게 확인할 수 없어 100이하로 제한하였습니다)
3.7) 상자 그림(Box Plot)
7번째는 상자 그림(box plot) 입니다. 상자 그림은 데이터의 분포와 이상치를 시각적으로 표현하는 방법으로, 중앙값, 사분위수 등을 보여줍니다.
# 'Age'와 'Survived' 열을 선택하여 상자 그림 그리기
plt.figure(figsize=(10, 6))
sns.boxplot(x='Survived', y='Age', data=df, palette='Set3')
plt.title('Box Plot of Age by Survived')
plt.xlabel('Survived')
plt.ylabel('Age')
plt.xticks([0, 1], ['Died', 'Survived'])
plt.show()

Box plot을 통해 데이터의 분포 및 범위와 이상치를 쉽게 확인할 수 있습니다.
04. 참고자료
[Kaggle] Titanic 생존자 예측 ① 데이터 확인 & EDA
[데이썬☀️_3편] 🔍EDA (탐색적 데이터 분석) 사용 설명서 (1) - EDA & 통계치 분석