데이터 분석가:Applied Data Analytics

Main Quest04 실습-3일차1st

데이터분석 2025. 2. 26. 19:43

3일차(2/26) : EDA와 feature engineering / 데이터 해석

  • 각 변수끼리의 상관관계 분석
  • 경향성, 패턴 등을 통해 인사이트 찾아내기
    • 인사이트를 통한 활용 방안 고민
  • 세운 가설을 시각화를 통해 증명하기

진행 순서와 해야 할 일

1. 변수 간 상관관계 분석

해야 할 일:

  • 상관계수 행렬 계산:
    • DataFrame의 corr() 메서드를 이용하여 변수 간의 상관계수를 산출합니다.
  • 히트맵 시각화:
    • seaborn의 heatmap 함수를 사용하여 상관관계 행렬을 시각적으로 표현합니다.

예제 코드:

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# (가정) 정제된 데이터셋: df
# 상관계수 행렬 계산
corr_matrix = df.corr()

# 상관관계 히트맵 시각화
plt.figure(figsize=(10, 8))
sns.heatmap(corr_matrix, annot=True, fmt=".2f", cmap='coolwarm')
plt.title("변수 간 상관관계")
plt.tight_layout()
plt.show()

2. 경향성 및 패턴 분석을 통한 인사이트 도출

해야 할 일:

  • 기초 통계량 및 분포 확인:
    • 각 변수의 분포(히스토그램, 박스플롯 등)를 확인하여 데이터의 경향성을 파악합니다.
  • 변수 간 관계 탐색:
    • 여러 변수 간의 분포 및 관계를 보기 위해 pairplot, scatter plot 등을 활용합니다.
  • 그룹별 집계 및 시각화:
    • 특정 기준(예, 범주형 변수)에 따른 집계를 통해 패턴을 분석합니다.
  • 인사이트 도출:
    • 위의 시각화 결과를 통해 어떤 변수들이 중요한 역할을 하는지, 어떠한 경향성이 있는지를 분석하고 활용 방안을 고민합니다.

예제 코드:

# 기초 통계량 출력
print(df.describe())

# 각 변수 분포 확인 (히스토그램)
df.hist(bins=30, figsize=(12, 10))
plt.tight_layout()
plt.show()

# 변수 간 관계 탐색 (pairplot)
sns.pairplot(df)
plt.tight_layout()
plt.show()

# 예: 범주형 변수 'category'에 따른 평균값 비교 (바 플롯)
plt.figure(figsize=(8, 6))
sns.barplot(x='category', y='target_variable', data=df, palette='viridis')
plt.title("범주별 타겟 변수 평균")
plt.tight_layout()
plt.show()

인사이트 예시:

  • 어떤 범주의 데이터가 평균적으로 높은 타겟 값을 가지는지
  • 특정 변수들 간에 강한 상관관계가 존재하는지

3. 세운 가설을 시각화를 통해 증명

해야 할 일:

  • 가설 설정:
    • 예를 들어 “변수 A와 변수 B는 양의 상관관계를 가진다”라는 가설을 세웁니다.
  • 관련 시각화 작성:
    • 산점도(scatter plot)를 이용해 두 변수 간의 관계를 시각적으로 표현하거나, 필요에 따라 선형 회귀선을 추가하여 관계를 명확히 합니다.
  • 결과 해석:
    • 시각화 결과를 토대로 가설의 타당성을 검토합니다.

예제 코드:

# 예: 변수 A와 변수 B 간의 양의 상관관계 가설 검증
plt.figure(figsize=(8, 6))
sns.scatterplot(x='A', y='B', data=df, color='blue')
sns.regplot(x='A', y='B', data=df, scatter=False, color='red')  # 회귀선 추가
plt.title("가설: 변수 A와 B 간의 양의 상관관계")
plt.xlabel("A 변수")
plt.ylabel("B 변수")
plt.tight_layout()
plt.show()

가설 검증 팁:

  • 산점도에 추가된 회귀선을 통해 두 변수의 관계가 뚜렷하게 양의 방향으로 나타난다면, 가설에 대한 시각적 증거가 될 수 있습니다.

이와 같이 3단계로 진행하면 데이터셋의 상관관계, 패턴, 그리고 세운 가설에 대한 시각적 검증을 효과적으로 수행할 수 있다. 필요에 따라 각 단계에서 추가 분석 및 시각화를 더 진행하면 좋다.


clean_data_df = pd.read_csv("/content/drive/MyDrive/아이펠_오마카세_프로젝트/clean_data.csv")

# 모든 컬럼 표시 옵션 설정 (옵션)
pd.set_option('display.max_columns', None)

clean_data_df

# 각 컬럼별 결측치 개수 확인  총3개의 컬럼에서 결측치 발견
print("결측치 현황:")
print(clean_data_df.isnull().sum())

# 중복 데이터 확인 중복데이터 없음
print("중복 행 수:", clean_data_df.duplicated().sum())
결측치 현황:
train_id             0
name                 0
item_condition_id    0
category_name        0
brand_name           0
price                0
shipping             0
item_description     0
dtype: int64
중복 행 수: 0

이상치 탐색의 가장 일반적인 방법 :

주요 연속형 변수(여기서는 주로 price 컬럼)에 대해 기술 통계량과 박스플롯(Boxplot)을 확인하고 IQR(Interquartile Range) 방법을 적용하는 것.

# 1. 기술 통계량 확인 (price 컬럼)
print("Price 컬럼 통계량:")
print(clean_data_df['price'].describe())

# 2. 박스플롯을 이용한 시각화
plt.figure(figsize=(10,6))
sns.boxplot(x=clean_data_df['price'])
plt.title("Price 컬럼 Boxplot")
plt.xlabel("Price")
plt.show()

# 3. IQR(Interquartile Range) 방법을 사용한 이상치 탐색
Q1 = clean_data_df['price'].quantile(0.25)
Q3 = clean_data_df['price'].quantile(0.75)
IQR = Q3 - Q1

lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

# 이상치에 해당하는 데이터
price_outliers = clean_data_df[(clean_data_df['price'] < lower_bound) | (clean_data_df['price'] > upper_bound)]

print("Price 컬럼 이상치 개수:", price_outliers.shape[0])
print("이상치 가격 값의 요약 통계:")
print(price_outliers['price'].describe())

Price 컬럼 이상치 개수: 119352
이상치 가격 값의 요약 통계:
count 119352.000000
mean 112.881146
std 93.847746
min 58.000000
25% 66.000000
50% 84.000000
75% 121.000000
max 2009.000000
Name: price, dtype: float64

  1. 이상치 제거 (Outlier Removal):
  2. 이상치 대체 (Outlier Treatment/Winsorization): 극단적인 값들을 lower_bound와 upper_bound 값으로 대체하여 데이터 분포의 왜곡을 줄이는 방법
# 2. 이상치를 lower_bound, upper_bound로 대체하는 방법 (윈저라이제이션)
clean_data_df['price_winsor'] = clean_data_df['price'].apply(
    lambda x: lower_bound if x < lower_bound else (upper_bound if x > upper_bound else x)
)

print("Winsorization 후 Price 컬럼 통계량:")
print(clean_data_df['price_winsor'].describe())

Winsorization 후 Price 컬럼 통계량:

count 1.481661e+06
mean 2.229218e+01
std 1.544646e+01
min 3.000000e+00
25% 1.000000e+01
50% 1.700000e+01
75% 2.900000e+01
max 5.750000e+01
Name: price_winsor, dtype: float64

Winsorization 후: 평균이 약 22.29로 감소하고, 표준편차도 약 15.45로 줄었다. 최대값이 57.5로 제한되어, 이상치의 영향이 크게 줄었다.
Winsorization을 통해 극단값의 영향을 충분히 줄였고, 데이터 분포가 분석에 적합해 보인다면 추가 조치는 필요하지 않음.

# 박스플롯: price_winsor 분포 확인
plt.figure(figsize=(12, 6))
sns.boxplot(x=clean_data_df['price_winsor'])
plt.title("Winsorization 후 Price 컬럼 Boxplot", fontsize=18)
plt.xlabel("Price_winsor", fontsize=14)
plt.show()

# 히스토그램 및 KDE: price_winsor 분포 확인
plt.figure(figsize=(12, 6))
sns.histplot(clean_data_df['price_winsor'], kde=True, bins=50, color='skyblue')
plt.title("Winsorization 후 Price 컬럼 Histogram", fontsize=18)
plt.xlabel("Price_winsor", fontsize=14)
plt.ylabel("Frequency", fontsize=14)
plt.show()

조치 결과 해석:

  1. 이상치(고가 제품)로 인한 분포 왜곡이 줄어듦

평균과 표준편차가 모두 감소하여, 모델 학습 시 고가 제품에 과도하게 끌려가는 현상이 완화될 수 있다.

  1. 상위 구간 값들이 인위적으로 동일하게 처리됨

실제로 60달러 이상의 제품들이 모두 58달러로 취급되므로, 해당 구간에서의 정밀도는 떨어질 수 있습니다. 고가 제품이 중요한 분석(예: 고가 제품만 대상으로 한 마케팅 전략 등)을 할 때는 도메인 지식과 목적에 따라 추가적인 고려가 필요합니다.

  1. 추가 변환(로그 변환 등) 고려

분포가 여전히 오른쪽으로 치우쳐 있다면, 로그 변환 등을 통해 더 정규분포에 가깝도록 만들 수 있습니다. 다만, 로그 변환 시 0 이하의 값이 없어야 하므로, 최소값(3달러)보다 더 작은 값이 있는지 확인하거나, price+1 형태로 변환을 적용하기도 합니다.

※ 실제 고가 구간 데이터를 모두 동일하게 처리했다는 점에서 분석 목적에 부합하는지? 추가적인 로그 변환 등이 필요하지 않은지? 검토필요

# 1. 이상치를 제거한 새로운 데이터셋 생성
cleaned_price_df = clean_data_df[(clean_data_df['price'] >= lower_bound) & (clean_data_df['price'] <= upper_bound)]

print("이상치 제거 후 Price 컬럼 통계량:")
print(cleaned_price_df['price'].describe())

이상치 제거 후 Price 컬럼 통계량:
count 1.362309e+06
mean 1.920762e+01
std 1.189038e+01
min 3.000000e+00
25% 1.000000e+01
50% 1.600000e+01
75% 2.500000e+01
max 5.750000e+01
Name: price, dtype: float64

결론 및 후속 조치

이상치 제거를 통해 극단값으로 인한 분포 왜곡을 줄이는 데 성공했으나,

모델링 시, 과도한 이상치로 인한 오버/언더피팅 위험이 낮아질 수 있다.

다만, 고가 제품을 모두 제외했다는 점에서,

고가 제품에 대한 분석이 중요하다면

도메인 지식과 목적에 따라 추가적인 처리가 필요(2. 이상치를 lower_bound, upper_bound로 대체하는 방법)

데이터로 가치를 만드는 Steven, Follow on LinkedIn