오늘은 데이터 전처리와 EDA를 세 가지 데이터에 적용했다. 타이타닉 데이터에서는 전처리 후 가설을 확인했고, 야후 파이낸스 데이터에서는 수익률과 낙폭을 계산했다. 마지막으로 HR 데이터에서 이직 여부와 근무 조건의 관계를 살펴봤다.
먼저 수치형 컬럼의 상관관계를 확인하고, Age의 결측값을 중앙값으로 채웠다. 이후 성별과 생존 여부를 묶어 비율을 계산했다.
pd.crosstab(df1["Sex"], df1["Survived"], normalize="index") * 100
실습 결과 여성의 생존 비율은 약 74.2%, 남성은 약 18.9%였다. Age < 18을 기준으로 아이 여부를 나누고, Parch가 0인지 여부와 생존율도 함께 비교했다.
전처리할 때는 값 하나를 이상치로 판단해 바꾸기 전에 기준을 다시 확인해야 한다는 점도 짚었다. 나이가 1세 미만인 행을 중앙값으로 바꾸는 코드가 있었는데, 단순히 작은 값이라는 이유만으로 수정하면 실제 데이터까지 잃을 수 있다.
yfinance로 JEPQ, JEPI, NVDA, MSFT의 2024년 1월부터 2026년 8월까지 종가 데이터를 가져왔다. 종목별 종가를 하나의 DataFrame으로 만들고, 일간 수익률과 누적 수익률을 계산했다.
returns_df = close_df.pct_change().dropna()
cum_returns_df = (1 + returns_df).cumprod() - 1
peak_df = close_df.cummax()
drawdown_df = (close_df - peak_df) / peak_df
cummax()로 시점별 최고가를 만든 뒤 현재 종가와 비교해 고점 대비 낙폭을 구했다. 실습 기간의 최대 낙폭은 JEPI -13.3%, JEPQ -20.1%, NVDA -36.9%, MSFT -34.5%로 계산됐다. 누적 수익률과 최대 낙폭은 같은 기간에도 서로 다른 모습을 보여서, 수익률만으로 종목의 흐름을 판단하기 어렵다는 점을 확인했다.
NVDA와 두 ETF의 20일 이동 상관계수도 계산했다.
rolling_jepi = returns_df["NVDA"].rolling(window=20).corr(returns_df["JEPI"])
rolling_jepq = returns_df["NVDA"].rolling(window=20).corr(returns_df["JEPQ"])
상관계수는 기간에 따라 달라졌고, 마지막 관측일에는 JEPQ가 약 0.59, JEPI가 약 -0.36이었다. 한 시점의 수치보다 시간에 따라 값이 어떻게 움직이는지 그래프로 보는 이유를 알 수 있었다.
고점 대비 낙폭을 네 구간으로 나눈 뒤, 각 날짜에서 20거래일 뒤 수익률도 집계했다.
fwd_return = close_df[t].shift(-20) / close_df[t] - 1
df_temp["구간"] = pd.cut(
df_temp["Drawdown"],
bins=[-1.0, -0.2, -0.1, -0.05, 0.001],
labels=["-20% 이하", "-10% ~ -20%", "-5% ~ -10%", "0% ~ -5%"]
)
구간별 승률과 평균 수익률을 계산할 수 있었지만, 일부 구간은 관측일이 1일 또는 4일뿐이었다. 집계값을 해석할 때는 수익률뿐 아니라 구간별 표본 수를 같이 봐야 한다.
IBM HR Analytics 데이터는 1,470행, 20개 컬럼으로 구성되어 있었고 결측값은 없었다. 범주형 변수는 교차표로, 수치형 변수는 그룹별 기술통계와 박스플롯으로 확인했다.
pd.crosstab(
df["OverTime"],
df["Attrition"],
normalize="index"
) * 100
초과근무를 하지 않는 그룹의 이직률은 약 10.4%, 초과근무 그룹은 약 30.5%였다. 이 결과는 두 변수 사이의 차이를 보여주지만, 초과근무가 이직을 직접 일으킨다는 뜻으로 해석할 수는 없다.
월 소득은 이직하지 않은 그룹의 평균이 약 6,833, 이직한 그룹은 약 4,787로 집계됐다. 마지막 승진 이후 기간은 길어질수록 이직률이 계속 높아질 것이라는 가설을 세웠지만, 결과는 일정하게 증가하지 않았다.
promotion_attrition = pd.crosstab(
df["YearsSinceLastPromotion"],
df["Attrition"],
normalize="index"
) * 100
가설과 다른 결과가 나왔을 때는 그대로 결론을 내리기보다, 각 기간 그룹의 인원수와 다른 근무 조건도 함께 확인해야 한다. Work-Life Balance가 1인 그룹의 이직률은 약 31.3%로 다른 점수 그룹보다 높게 나타났다.
오늘 실습에서는 데이터를 정리한 뒤 groupby, 교차표, 누적 수익률, 낙폭, 이동 상관계수처럼 목적에 맞는 지표를 골라 비교했다. 결과를 볼 때는 가설이 맞았는지만 보기보다, 전처리 기준과 표본 수, 지표가 실제로 의미하는 범위를 같이 확인해야겠다.