EDA 도구 활용 - 효율적인 탐색적 데이터 분석
EDA 도구 활용 - 효율적인 탐색적 데이터 분석
EDA 도구 활용 - 효율적인 탐색적 데이터 분석
개요
효율적인 탐색적 데이터 분석을 위한 자동화 도구를 학습합니다:
- EDA 도구: Sweetviz, Pandas Profiling, DataPrep, AutoViz
- 자동화 분석: 데이터 개요, 통계 분석, 시각화
- 실무 활용: 데이터 품질 검사, 모델링 전 탐색
- 고급 기법: 커스터마이징, 대용량 데이터 처리
1. EDA 도구 개요
1-1. 주요 EDA 도구
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
print("=== 주요 EDA 도구 ===")
print("1. Sweetviz")
print(" - 자동 EDA 보고서 생성")
print(" - HTML 형태의 인터랙티브 리포트")
print(" - 데이터셋 비교 분석 지원")
print(" - 타겟 변수 지정 가능")
print("\n2. Pandas Profiling")
print(" - 상세한 데이터 프로파일링")
print(" - 통계적 분석과 시각화")
print(" - 상관관계 분석")
print(" - 이상치 탐지")
print("\n3. DataPrep")
print(" - 빠른 데이터 탐색")
print(" - 데이터 클리닝 기능")
print(" - 시각화 자동 생성")
print(" - 웹 기반 인터페이스")
print("\n4. AutoViz")
print(" - 자동 시각화 생성")
print(" - 다양한 차트 타입")
print(" - 최적 차트 선택")
print(" - 빠른 인사이트 도출")
1-2. EDA 도구의 장점
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
print("=== EDA 도구의 장점 ===")
print("1. 시간 절약")
print(" - 수동 분석 대비 빠른 인사이트 도출")
print(" - 반복적인 분석 작업 자동화")
print(" - 표준화된 분석 프로세스")
print("\n2. 일관성")
print(" - 동일한 분석 기준 적용")
print(" - 누락 없는 체계적 분석")
print(" - 재현 가능한 결과")
print("\n3. 완전성")
print(" - 놓치기 쉬운 패턴 발견")
print(" - 포괄적인 데이터 검사")
print(" - 숨겨진 관계성 탐지")
print("\n4. 시각화")
print(" - 자동 생성되는 차트와 그래프")
print(" - 인터랙티브 시각화")
print(" - 보고서 형태의 결과")
2. Sweetviz 활용
2-1. 설치 및 기본 사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import pandas as pd
import numpy as np
import sweetviz as sv
import warnings
warnings.filterwarnings(action='ignore')
# 샘플 데이터 생성 (실제 데이터가 없는 경우)
np.random.seed(42)
n_samples = 1000
# 다양한 타입의 데이터 생성
data = {
'id': range(1, n_samples + 1),
'age': np.random.normal(35, 10, n_samples),
'income': np.random.lognormal(10, 0.5, n_samples),
'education': np.random.choice(['High School', 'Bachelor', 'Master', 'PhD'], n_samples),
'city': np.random.choice(['Seoul', 'Busan', 'Incheon', 'Daegu'], n_samples),
'satisfaction': np.random.choice([1, 2, 3, 4, 5], n_samples),
'target': np.random.choice([0, 1], n_samples, p=[0.7, 0.3])
}
df_train = pd.DataFrame(data)
print("=== Sweetviz 기본 사용 ===")
print(f"데이터 크기: {df_train.shape}")
print(f"컬럼: {list(df_train.columns)}")
# 단일 데이터셋 분석
my_report = sv.analyze(df_train)
my_report.show_html('./sweet_report.html')
print("Sweetviz 리포트가 'sweet_report.html'로 생성되었습니다.")
2-2. 비교 분석
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 테스트 데이터 생성 (약간 다른 분포)
df_test = pd.DataFrame({
'id': range(1001, 1501),
'age': np.random.normal(32, 8, 500), # 약간 다른 분포
'income': np.random.lognormal(9.5, 0.6, 500),
'education': np.random.choice(['High School', 'Bachelor', 'Master', 'PhD'], 500),
'city': np.random.choice(['Seoul', 'Busan', 'Incheon', 'Daegu'], 500),
'satisfaction': np.random.choice([1, 2, 3, 4, 5], 500),
'target': np.random.choice([0, 1], 500, p=[0.6, 0.4]) # 다른 비율
})
# 두 데이터셋 비교
compare_report = sv.compare([df_train, 'Train'], [df_test, 'Test'])
compare_report.show_html('./compare_report.html')
print("비교 분석 리포트가 'compare_report.html'로 생성되었습니다.")
2-3. 타겟 변수 지정
1
2
3
4
5
6
7
8
9
10
# 타겟 변수 지정하여 분석
target_report = sv.analyze(df_train, target_feat='target')
target_report.show_html('./target_report.html')
print("타겟 변수 분석 리포트가 'target_report.html'로 생성되었습니다.")
print("주요 분석 내용:")
print("- 타겟 변수 분포")
print("- 각 피처와 타겟의 관계")
print("- 클래스별 통계")
print("- 상관관계 분석")
2-4. 특정 변수만 분석
1
2
3
4
5
6
7
8
9
10
11
# 특정 변수들만 선택하여 분석
feature_config = sv.FeatureConfig(
skip=['id'], # ID 컬럼 제외
force_cat=['education', 'city'], # 범주형으로 강제 변환
force_num=['satisfaction'] # 수치형으로 강제 변환
)
filtered_report = sv.analyze(df_train, feature_config=feature_config)
filtered_report.show_html('./filtered_report.html')
print("필터링된 분석 리포트가 'filtered_report.html'로 생성되었습니다.")
3. Pandas Profiling 활용
3-1. 기본 사용
1
2
3
4
5
6
7
8
9
10
11
12
try:
from pandas_profiling import ProfileReport
# 프로파일링 리포트 생성
profile = ProfileReport(df_train, title="데이터 프로파일링 리포트")
profile.to_file("profile_report.html")
print("Pandas Profiling 리포트가 'profile_report.html'로 생성되었습니다.")
except ImportError:
print("Pandas Profiling이 설치되지 않았습니다.")
print("설치 명령: pip install pandas-profiling")
3-2. 설정 커스터마이징
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
try:
# 상세 설정
profile = ProfileReport(
df_train,
title="커스텀 프로파일링 리포트",
explorative=True, # 탐색적 분석 활성화
minimal=False, # 상세 분석
progress_bar=True, # 진행률 표시
correlations={
"pearson": {"calculate": True},
"spearman": {"calculate": True},
"kendall": {"calculate": True}
}
)
profile.to_file("custom_report.html")
print("커스텀 프로파일링 리포트가 'custom_report.html'로 생성되었습니다.")
except ImportError:
print("Pandas Profiling을 사용할 수 없습니다.")
3-3. Jupyter 노트북에서 표시
1
2
3
4
5
6
# 노트북에서 직접 표시 (실제 노트북 환경에서만 동작)
try:
# profile.to_notebook_iframe() # 주석 해제하여 사용
print("노트북에서 profile.to_notebook_iframe()을 사용하여 리포트를 표시할 수 있습니다.")
except:
print("Jupyter 노트북 환경이 아닙니다.")
4. 주요 분석 내용
4-1. 데이터 개요
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def analyze_data_overview(df):
"""데이터 개요 분석"""
print("=== 데이터 개요 ===")
print(f"데이터셋 크기: {df.shape}")
print(f"메모리 사용량: {df.memory_usage(deep=True).sum() / 1024**2:.2f} MB")
print(f"변수 수: {df.shape[1]}")
print(f"관측치 수: {df.shape[0]}")
print("\n=== 변수 타입 ===")
print(df.dtypes.value_counts())
print("\n=== 중복 데이터 ===")
duplicates = df.duplicated().sum()
print(f"중복 행 수: {duplicates}개 ({duplicates/len(df)*100:.1f}%)")
print("\n=== 결측값 ===")
missing_data = df.isnull().sum()
missing_ratio = (missing_data / len(df)) * 100
for col, ratio in missing_ratio.items():
if ratio > 0:
print(f"{col}: {missing_data[col]}개 ({ratio:.1f}%)")
if missing_ratio.sum() == 0:
print("결측값 없음")
# 데이터 개요 분석 실행
analyze_data_overview(df_train)
4-2. 수치형 변수 분석
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def analyze_numeric_variables(df):
"""수치형 변수 분석"""
numeric_cols = df.select_dtypes(include=[np.number]).columns
print("=== 수치형 변수 분석 ===")
for col in numeric_cols:
print(f"\n{col}:")
print(f" 평균: {df[col].mean():.2f}")
print(f" 중앙값: {df[col].median():.2f}")
print(f" 표준편차: {df[col].std():.2f}")
print(f" 최소값: {df[col].min():.2f}")
print(f" 최대값: {df[col].max():.2f}")
# 이상치 탐지 (IQR 방법)
Q1 = df[col].quantile(0.25)
Q3 = df[col].quantile(0.75)
IQR = Q3 - Q1
outliers = df[(df[col] < Q1 - 1.5*IQR) | (df[col] > Q3 + 1.5*IQR)]
print(f" 이상치: {len(outliers)}개 ({len(outliers)/len(df)*100:.1f}%)")
# 수치형 변수 분석 실행
analyze_numeric_variables(df_train)
4-3. 범주형 변수 분석
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def analyze_categorical_variables(df):
"""범주형 변수 분석"""
categorical_cols = df.select_dtypes(include=['object', 'category']).columns
print("=== 범주형 변수 분석 ===")
for col in categorical_cols:
print(f"\n{col}:")
print(f" 고유값 수: {df[col].nunique()}")
print(f" 최빈값: {df[col].mode().iloc[0] if len(df[col].mode()) > 0 else 'N/A'}")
print(f" 최빈값 빈도: {df[col].value_counts().iloc[0] if len(df[col].value_counts()) > 0 else 0}")
# 클래스 불균형 확인
value_counts = df[col].value_counts()
max_ratio = value_counts.iloc[0] / len(df)
print(f" 최대 클래스 비율: {max_ratio:.1%}")
if max_ratio > 0.8:
print(" ⚠️ 클래스 불균형 심각")
elif max_ratio > 0.6:
print(" ⚠️ 클래스 불균형 있음")
# 범주형 변수 분석 실행
analyze_categorical_variables(df_train)
4-4. 변수 간 관계 분석
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import matplotlib.pyplot as plt
import seaborn as sns
def analyze_variable_relationships(df):
"""변수 간 관계 분석"""
print("=== 변수 간 관계 분석 ===")
# 수치형 변수 간 상관관계
numeric_cols = df.select_dtypes(include=[np.number]).columns
if len(numeric_cols) > 1:
correlation_matrix = df[numeric_cols].corr()
# 상관관계 히트맵
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', center=0)
plt.title('수치형 변수 간 상관관계')
plt.tight_layout()
plt.show()
# 높은 상관관계 찾기
high_corr = []
for i in range(len(correlation_matrix.columns)):
for j in range(i+1, len(correlation_matrix.columns)):
corr_val = correlation_matrix.iloc[i, j]
if abs(corr_val) > 0.7:
high_corr.append((correlation_matrix.columns[i],
correlation_matrix.columns[j], corr_val))
if high_corr:
print("높은 상관관계 (|r| > 0.7):")
for var1, var2, corr in high_corr:
print(f" {var1} - {var2}: {corr:.3f}")
else:
print("높은 상관관계 없음")
# 범주형-수치형 변수 관계
categorical_cols = df.select_dtypes(include=['object', 'category']).columns
if len(categorical_cols) > 0 and len(numeric_cols) > 0:
print(f"\n범주형-수치형 변수 관계 분석 가능:")
print(f" 범주형: {list(categorical_cols)}")
print(f" 수치형: {list(numeric_cols)}")
# 변수 간 관계 분석 실행
analyze_variable_relationships(df_train)
5. 실무 활용 사례
5-1. 데이터 품질 검사
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
def data_quality_check(df, target_col=None):
"""데이터 품질 검사"""
print("=== 데이터 품질 검사 ===")
# 1. 기본 정보
print(f"데이터 크기: {df.shape}")
print(f"메모리 사용량: {df.memory_usage(deep=True).sum() / 1024**2:.2f} MB")
# 2. 결측값 패턴
missing_data = df.isnull().sum()
missing_ratio = (missing_data / len(df)) * 100
print("\n결측값 패턴:")
if missing_ratio.sum() > 0:
for col, ratio in missing_ratio.items():
if ratio > 0:
print(f" {col}: {missing_data[col]}개 ({ratio:.1f}%)")
else:
print(" 결측값 없음")
# 3. 이상치 분포
numeric_cols = df.select_dtypes(include=[np.number]).columns
print("\n이상치 분포:")
for col in numeric_cols:
Q1 = df[col].quantile(0.25)
Q3 = df[col].quantile(0.75)
IQR = Q3 - Q1
outliers = df[(df[col] < Q1 - 1.5*IQR) | (df[col] > Q3 + 1.5*IQR)]
outlier_ratio = len(outliers) / len(df) * 100
print(f" {col}: {len(outliers)}개 ({outlier_ratio:.1f}%)")
# 4. 데이터 타입 일관성
print("\n데이터 타입 일관성:")
for col in df.columns:
if df[col].dtype == 'object':
# 숫자로 변환 가능한 문자열 확인
try:
pd.to_numeric(df[col], errors='raise')
print(f" {col}: 숫자로 변환 가능한 문자열 포함")
except:
pass
# 5. 중복 데이터
duplicates = df.duplicated().sum()
print(f"\n중복 데이터: {duplicates}개 ({duplicates/len(df)*100:.1f}%)")
# 6. 타겟 변수 분석 (지정된 경우)
if target_col and target_col in df.columns:
print(f"\n타겟 변수 ({target_col}) 분석:")
if df[target_col].dtype in ['object', 'category']:
print(f" 클래스 분포: {df[target_col].value_counts().to_dict()}")
else:
print(f" 평균: {df[target_col].mean():.2f}")
print(f" 표준편차: {df[target_col].std():.2f}")
# 데이터 품질 검사 실행
data_quality_check(df_train, target_col='target')
5-2. 모델링 전 데이터 탐색
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
def pre_modeling_exploration(df, target_col):
"""모델링 전 데이터 탐색"""
print(f"=== 모델링 전 데이터 탐색 (타겟: {target_col}) ===")
# 1. 타겟 변수 분포
print("\n1. 타겟 변수 분포:")
if df[target_col].dtype in ['object', 'category']:
target_dist = df[target_col].value_counts()
print(target_dist)
# 클래스 불균형 확인
max_ratio = target_dist.iloc[0] / len(df)
print(f"최대 클래스 비율: {max_ratio:.1%}")
if max_ratio > 0.8:
print("⚠️ 심각한 클래스 불균형 - 샘플링 전략 필요")
elif max_ratio > 0.6:
print("⚠️ 클래스 불균형 - 가중치 조정 고려")
else:
print(f"평균: {df[target_col].mean():.2f}")
print(f"표준편차: {df[target_col].std():.2f}")
print(f"최소값: {df[target_col].min():.2f}")
print(f"최대값: {df[target_col].max():.2f}")
# 2. 피처-타겟 관계
print("\n2. 피처-타겟 관계:")
numeric_features = df.select_dtypes(include=[np.number]).columns
numeric_features = numeric_features.drop(target_col) if target_col in numeric_features else numeric_features
for feature in numeric_features:
if df[target_col].dtype in ['object', 'category']:
# 범주형 타겟의 경우 그룹별 통계
group_stats = df.groupby(target_col)[feature].agg(['mean', 'std'])
print(f" {feature}:")
for target_val in group_stats.index:
mean_val = group_stats.loc[target_val, 'mean']
std_val = group_stats.loc[target_val, 'std']
print(f" {target_val}: {mean_val:.2f} ± {std_val:.2f}")
else:
# 수치형 타겟의 경우 상관관계
corr = df[feature].corr(df[target_col])
print(f" {feature}: 상관계수 = {corr:.3f}")
# 3. 피처 중요도 (간단한 방법)
print("\n3. 피처 중요도 (상관관계 기반):")
if df[target_col].dtype in ['object', 'category']:
# 범주형 타겟의 경우 ANOVA F-score 계산
from sklearn.feature_selection import f_classif
X = df[numeric_features]
y = df[target_col]
f_scores, _ = f_classif(X, y)
feature_importance = pd.DataFrame({
'feature': numeric_features,
'f_score': f_scores
}).sort_values('f_score', ascending=False)
print(feature_importance)
else:
# 수치형 타겟의 경우 상관관계
correlations = df[numeric_features].corrwith(df[target_col]).abs().sort_values(ascending=False)
print(correlations)
# 모델링 전 데이터 탐색 실행
pre_modeling_exploration(df_train, 'target')
5-3. 데이터 전처리 계획 수립
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
def preprocessing_plan(df):
"""데이터 전처리 계획 수립"""
print("=== 데이터 전처리 계획 ===")
preprocessing_steps = []
# 1. 결측값 처리
missing_data = df.isnull().sum()
if missing_data.sum() > 0:
print("1. 결측값 처리 필요:")
for col, count in missing_data.items():
if count > 0:
ratio = count / len(df)
if ratio > 0.5:
preprocessing_steps.append(f" - {col}: 삭제 (결측률 {ratio:.1%})")
elif ratio > 0.1:
preprocessing_steps.append(f" - {col}: 고급 대체 방법 (결측률 {ratio:.1%})")
else:
preprocessing_steps.append(f" - {col}: 단순 대체 (결측률 {ratio:.1%})")
# 2. 이상치 처리
numeric_cols = df.select_dtypes(include=[np.number]).columns
outlier_cols = []
for col in numeric_cols:
Q1 = df[col].quantile(0.25)
Q3 = df[col].quantile(0.75)
IQR = Q3 - Q1
outliers = df[(df[col] < Q1 - 1.5*IQR) | (df[col] > Q3 + 1.5*IQR)]
if len(outliers) / len(df) > 0.05: # 5% 이상
outlier_cols.append(col)
if outlier_cols:
preprocessing_steps.append("2. 이상치 처리:")
for col in outlier_cols:
preprocessing_steps.append(f" - {col}: 이상치 탐지 및 처리")
# 3. 데이터 타입 변환
categorical_cols = df.select_dtypes(include=['object']).columns
if len(categorical_cols) > 0:
preprocessing_steps.append("3. 범주형 변수 인코딩:")
for col in categorical_cols:
unique_count = df[col].nunique()
if unique_count <= 10:
preprocessing_steps.append(f" - {col}: 원핫 인코딩 ({unique_count}개 카테고리)")
else:
preprocessing_steps.append(f" - {col}: 타겟 인코딩 또는 삭제 고려 ({unique_count}개 카테고리)")
# 4. 스케일링
if len(numeric_cols) > 0:
preprocessing_steps.append("4. 수치형 변수 스케일링:")
preprocessing_steps.append(" - StandardScaler 또는 MinMaxScaler 적용")
# 5. 피처 선택
preprocessing_steps.append("5. 피처 선택:")
preprocessing_steps.append(" - 상관관계가 높은 피처 제거")
preprocessing_steps.append(" - 분산이 낮은 피처 제거")
preprocessing_steps.append(" - 도메인 지식 기반 피처 선택")
# 결과 출력
if preprocessing_steps:
for step in preprocessing_steps:
print(step)
else:
print("전처리가 필요하지 않습니다.")
# 전처리 계획 수립
preprocessing_plan(df_train)
6. 고급 활용 기법
6-1. 커스텀 설정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def advanced_sweetviz_analysis(df):
"""고급 Sweetviz 분석"""
print("=== 고급 Sweetviz 분석 ===")
# 커스텀 설정
feature_config = sv.FeatureConfig(
skip=['id'], # ID 컬럼 제외
force_cat=['education', 'city'], # 범주형으로 강제 변환
force_num=['satisfaction'], # 수치형으로 강제 변환
force_text=[], # 텍스트로 강제 변환
force_date=[] # 날짜로 강제 변환
)
# 고급 분석 설정
advanced_report = sv.analyze(
df,
target_feat='target',
feature_config=feature_config,
pairwise_analysis='on' # 쌍별 분석 활성화
)
advanced_report.show_html('./advanced_report.html')
print("고급 분석 리포트가 'advanced_report.html'로 생성되었습니다.")
# 고급 분석 실행
advanced_sweetviz_analysis(df_train)
6-2. 대용량 데이터 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def large_data_analysis(df, sample_size=10000):
"""대용량 데이터 분석"""
print("=== 대용량 데이터 분석 ===")
if len(df) > sample_size:
print(f"데이터 크기: {len(df)} → {sample_size} (샘플링)")
# 계층적 샘플링 (타겟 변수가 있는 경우)
if 'target' in df.columns:
sample_df = df.groupby('target').apply(
lambda x: x.sample(min(len(x), sample_size // df['target'].nunique()))
).reset_index(drop=True)
else:
sample_df = df.sample(n=sample_size, random_state=42)
# 샘플 데이터로 분석
sample_report = sv.analyze(sample_df)
sample_report.show_html('./sample_report.html')
print("샘플 분석 리포트가 'sample_report.html'로 생성되었습니다.")
return sample_df
else:
print(f"데이터 크기가 작아 샘플링이 필요하지 않습니다: {len(df)}")
return df
# 대용량 데이터 분석 실행
sample_data = large_data_analysis(df_train)
6-3. 시계열 데이터 분석
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def time_series_analysis():
"""시계열 데이터 분석"""
print("=== 시계열 데이터 분석 ===")
# 시계열 데이터 생성
dates = pd.date_range('2023-01-01', periods=365, freq='D')
time_series_data = pd.DataFrame({
'date': dates,
'value': np.cumsum(np.random.randn(365)) + 100,
'category': np.random.choice(['A', 'B', 'C'], 365),
'target': np.random.choice([0, 1], 365, p=[0.6, 0.4])
})
print(f"시계열 데이터 크기: {time_series_data.shape}")
# 시계열 특화 분석
time_series_report = sv.analyze(
time_series_data,
target_feat='target',
pairwise_analysis='on'
)
time_series_report.show_html('./timeseries_report.html')
print("시계열 분석 리포트가 'timeseries_report.html'로 생성되었습니다.")
return time_series_data
# 시계열 데이터 분석 실행
ts_data = time_series_analysis()
7. 보고서 활용
7-1. HTML 보고서 활용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def html_report_utilization():
"""HTML 보고서 활용 방법"""
print("=== HTML 보고서 활용 ===")
print("1. HTML 보고서의 장점:")
print(" - 인터랙티브한 탐색")
print(" - 클라이언트와의 공유 용이")
print(" - 팀 내 협업 도구")
print(" - 웹 브라우저에서 직접 확인")
print("\n2. 활용 방법:")
print(" - 데이터 품질 검사 결과 공유")
print(" - 모델링 전 데이터 탐색 보고")
print(" - 정기적인 데이터 모니터링")
print(" - 새로운 데이터셋 검증")
print("\n3. 보고서 구성 요소:")
print(" - 데이터 개요 및 통계")
print(" - 변수별 상세 분석")
print(" - 변수 간 관계 분석")
print(" - 이상치 및 결측값 정보")
print(" - 시각화 차트")
html_report_utilization()
7-2. 자동화된 EDA 파이프라인
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
def automated_eda_pipeline(df, project_name="EDA_Analysis"):
"""자동화된 EDA 파이프라인"""
print(f"=== 자동화된 EDA 파이프라인: {project_name} ===")
import os
from datetime import datetime
# 결과 폴더 생성
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
output_dir = f"./eda_reports/{project_name}_{timestamp}"
os.makedirs(output_dir, exist_ok=True)
# 1. 기본 분석
print("1. 기본 분석 실행 중...")
basic_report = sv.analyze(df)
basic_report.show_html(f"{output_dir}/basic_analysis.html")
# 2. 타겟 변수 분석 (있는 경우)
target_cols = [col for col in df.columns if 'target' in col.lower() or 'label' in col.lower()]
if target_cols:
print(f"2. 타겟 변수 분석 실행 중... (타겟: {target_cols[0]})")
target_report = sv.analyze(df, target_feat=target_cols[0])
target_report.show_html(f"{output_dir}/target_analysis.html")
# 3. 데이터 품질 리포트
print("3. 데이터 품질 리포트 생성 중...")
quality_summary = {
'data_size': df.shape,
'memory_usage': df.memory_usage(deep=True).sum() / 1024**2,
'missing_data': df.isnull().sum().to_dict(),
'duplicate_rows': df.duplicated().sum(),
'data_types': df.dtypes.to_dict()
}
# 품질 리포트를 텍스트 파일로 저장
with open(f"{output_dir}/quality_summary.txt", 'w', encoding='utf-8') as f:
f.write(f"데이터 품질 요약\n")
f.write(f"================\n\n")
f.write(f"데이터 크기: {quality_summary['data_size']}\n")
f.write(f"메모리 사용량: {quality_summary['memory_usage']:.2f} MB\n")
f.write(f"중복 행 수: {quality_summary['duplicate_rows']}\n\n")
f.write(f"결측값:\n")
for col, count in quality_summary['missing_data'].items():
if count > 0:
f.write(f" {col}: {count}개\n")
f.write(f"\n데이터 타입:\n")
for col, dtype in quality_summary['data_types'].items():
f.write(f" {col}: {dtype}\n")
print(f"EDA 파이프라인 완료!")
print(f"결과 저장 위치: {output_dir}")
print(f"생성된 파일:")
print(f" - basic_analysis.html")
if target_cols:
print(f" - target_analysis.html")
print(f" - quality_summary.txt")
return output_dir
# 자동화된 EDA 파이프라인 실행
output_directory = automated_eda_pipeline(df_train, "Sample_Project")
마무리
EDA 도구를 효과적으로 활용하면 데이터 분석의 효율성을 크게 향상시킬 수 있습니다:
핵심 학습 내용
- EDA 도구: Sweetviz, Pandas Profiling의 특성과 활용법
- 자동화 분석: 데이터 개요, 통계 분석, 시각화 자동 생성
- 실무 활용: 데이터 품질 검사, 모델링 전 탐색, 전처리 계획
- 고급 기법: 커스터마이징, 대용량 데이터 처리, 시계열 분석
실무 적용
- 자동화 파이프라인: 반복적인 EDA 작업의 자동화
- 품질 관리: 체계적인 데이터 품질 검사
- 협업 도구: HTML 보고서를 통한 팀 내 공유
- 지속적 모니터링: 정기적인 데이터 품질 모니터링
EDA 도구는 데이터 분석의 시작점으로, 도메인 지식과 결합하여 더 깊이 있는 인사이트를 도출할 수 있습니다.
This post is licensed under CC BY 4.0 by the author.