데이터 분석 및 정리 방안
1. 칼럼 정리
- Unnamed: 0: 인덱스로 보이며 삭제 가능.
- Grading Date: 날짜 데이터이므로 datetime 형식으로 변환.
- Harvest Year: 일부 결측치 존재, 예측 또는 삭제 여부 결정 필요.
- altitude_mean_meters: 결측치 존재, 평균 또는 중위수로 대체 가능.
- Processing Method, Region, Color: 범주형 데이터, 결측치 처리 필요.
2. 이상치 처리
- Moisture Percentage: 0.0의 값이 존재하는데, 일반적인 수분 함량은 10~12%이므로 이상치 가능성 있음.
- Total Cup Points, Aroma, Flavor 등 점수 관련 칼럼: 값의 분포를 확인 후 극단값 처리 필요.
3. 결측치 처리
- 수치형 데이터 (altitude_mean_meters, Harvest Year): 평균 또는 중앙값 대체.
- 범주형 데이터 (Processing Method, Region, Color): 최빈값 대체 또는 "Unknown" 처리.
우선 이상치 및 결측치 비율을 더 자세히 확인한 후 정리 방향을 결정하겠습니다.
결과 분석 및 정리 방안
1. 결측치 처리
- 범주형 데이터 (Processing Method, Region, Color)
- Processing Method(8.33% 결측): 최빈값 또는 "Unknown"으로 대체.
- Region(3.10% 결측): 최빈값으로 대체 가능, 또는 "Unknown".
- Color(20.02% 결측): 결측 비율이 높아 "Unknown"으로 대체하는 것이 적절.
- 수치형 데이터 (altitude_mean_meters, Harvest Year)
- altitude_mean_meters(3.74% 결측): 중앙값으로 대체.
- Harvest Year(2.99% 결측): 평균값 대체 가능하나, 최신 연도(2022년)와의 차이 분석 후 판단.
2. 이상치 처리
- Moisture Percentage: 최소값이 0.0, 최대값이 28.0으로 범위를 벗어나는 값 존재. 정상 범위(10~12%) 밖의 값은 중앙값으로 대체.
- Category One Defects, Category Two Defects: 최대값이 31, 55로 상당히 크므로 이상치 필터링 필요.
- Bag Weight: 최소값이 0.0, 최대값이 21,600.0. 일반적인 커피 가방 무게(1~70kg) 이상은 제거 또는 조정 필요.
# 결측치 비율 확인
missing_values = df.isnull().sum() / len(df) * 100
missing_values = missing_values[missing_values > 0].sort_values(ascending=False)
# 이상치 확인 (수치형 데이터의 기본 통계)
numeric_summary = df.describe()
# 결과 출력
missing_values, numeric_summary
# 1. 불필요한 칼럼 제거
df_cleaned = df.drop(columns=["Unnamed: 0"])
# 2. 결측치 처리
df_cleaned["Processing Method"].fillna("Unknown", inplace=True)
df_cleaned["Region"].fillna("Unknown", inplace=True)
df_cleaned["Color"].fillna("Unknown", inplace=True)
df_cleaned["altitude_mean_meters"].fillna(df_cleaned["altitude_mean_meters"].median(), inplace=True)
df_cleaned["Harvest Year"].fillna(round(df_cleaned["Harvest Year"].mean()), inplace=True)
# 3. 이상치 처리
# Moisture Percentage: 10~12% 이내로 조정
df_cleaned.loc[df_cleaned["Moisture Percentage"] < 10, "Moisture Percentage"] = df_cleaned["Moisture Percentage"].median()
df_cleaned.loc[df_cleaned["Moisture Percentage"] > 12, "Moisture Percentage"] = df_cleaned["Moisture Percentage"].median()
# Bag Weight: 일반적인 범위(1~70kg)로 제한
df_cleaned = df_cleaned[(df_cleaned["Bag Weight"] > 1) & (df_cleaned["Bag Weight"] < 70)]
# Category One Defects, Category Two Defects: 99th 퍼센타일 초과 값 제거
q1_defect_threshold = df_cleaned["Category One Defects"].quantile(0.99)
q2_defect_threshold = df_cleaned["Category Two Defects"].quantile(0.99)
df_cleaned = df_cleaned[(df_cleaned["Category One Defects"] <= q1_defect_threshold) &
(df_cleaned["Category Two Defects"] <= q2_defect_threshold)]
df_cleaned.to_csv("cleaned_quakers_data.csv", index=False)
from google.colab import files
files.download("cleaned_quakers_data.csv")
import missingno as msno
import matplotlib.pyplot as plt
msno.bar(df_cleaned)
plt.show()
sns.scatterplot(x=df_cleaned["altitude_mean_meters"], y=df_cleaned["Total Cup Points"])
plt.xlabel("Altitude (m)")
plt.ylabel("Total Cup Points")
plt.show()