스토리텔링 형식으로 업데이트되었습니다! 실무 사례와 함께 더 쉽게 이해할 수 있어요.
이미지 로딩 중...
AI Generated
2025. 11. 25. · 10 Views
이변량 분석 완벽 가이드: 변수 간 관계 탐색
두 변수 사이의 관계를 분석하는 이변량 분석의 핵심 개념과 기법을 배웁니다. 상관관계, 산점도, 교차분석 등 데이터 분석의 필수 도구들을 실습과 함께 익혀봅시다.
목차
1. 이변량_분석_기초
여러분이 "아이스크림 판매량이 늘어날 때 익사 사고도 늘어난다"는 뉴스를 본 적 있나요? 이게 정말 아이스크림이 익사를 유발한다는 뜻일까요?
아니면 둘 다 여름이라는 공통 원인이 있는 걸까요? 이런 의문을 해결하려면 두 변수 사이의 관계를 제대로 분석해야 합니다.
단순히 "같이 올라간다"고 해서 원인과 결과라고 단정 지을 수 없기 때문이죠. 바로 이럴 때 필요한 것이 이변량 분석입니다.
두 변수 사이에 정말 의미 있는 관계가 있는지, 있다면 얼마나 강한지를 과학적으로 알아내는 방법입니다.
간단히 말해서, 이변량 분석은 두 개의 변수 사이에 어떤 관계가 있는지 알아보는 분석 방법입니다. 마치 키와 몸무게처럼 서로 연관이 있을 것 같은 두 가지를 함께 살펴보는 것이죠.
왜 이변량 분석이 필요할까요? 데이터 분석에서 우리는 종종 "A가 변하면 B도 변할까?"라는 질문을 합니다.
예를 들어, 광고비를 늘리면 매출이 올라갈까? 공부 시간을 늘리면 성적이 좋아질까?
이런 질문에 답하려면 반드시 두 변수를 함께 분석해야 합니다. 한 변수만 보는 것을 일변량 분석이라고 합니다.
평균, 중앙값 같은 것들이죠. 하지만 이것만으로는 변수들 사이의 관계를 알 수 없습니다.
이변량 분석은 여기서 한 걸음 더 나아가 "관계"를 탐색합니다. 이변량 분석의 핵심 특징은 첫째, 두 변수의 동시 변화를 관찰한다는 점, 둘째, 관계의 방향(같이 증가하는지, 반대로 움직이는지)을 파악한다는 점, 셋째, 관계의 강도를 숫자로 표현할 수 있다는 점입니다.
다음 코드를 살펴봅시다.
import pandas as pd
import numpy as np
# 예시 데이터: 공부 시간과 시험 점수
data = {
'study_hours': [1, 2, 3, 4, 5, 6, 7, 8],
'test_score': [50, 55, 65, 70, 75, 85, 88, 95]
}
df = pd.DataFrame(data)
# 두 변수의 기본 통계량 확인
print("공부 시간 평균:", df['study_hours'].mean())
print("시험 점수 평균:", df['test_score'].mean())
# 두 변수 사이의 공분산 계산
covariance = df['study_hours'].cov(df['test_score'])
print("공분산:", covariance)
도입 스토리 마케팅팀의 지수는 고민에 빠졌다. 지난 6개월간 광고비를 계속 늘렸는데, 매출이 정말 그 덕분에 올랐는지 확신이 없었다.
단순히 숫자가 같이 올랐다고 해서 광고가 효과적이라고 보고하기엔 뭔가 부족했다. 이변량 분석이란? 이변량 분석은 두 개의 변수를 동시에 살펴보며 그들 사이의 관계를 파악하는 방법입니다.
마치 시소의 양쪽 끝처럼, 한쪽이 올라가면 다른 쪽이 어떻게 반응하는지 관찰하는 것과 같습니다. 기존 방식의 문제점: - 일변량 분석만으로는 관계를 알 수 없음: 각 변수의 평균만 봐서는 연결고리를 찾을 수 없습니다 - 직관에만 의존함: "느낌상 관련 있을 것 같다"는 것은 과학적이지 않습니다 - 우연의 일치를 구분하지 못함: 같이 변했다고 해서 반드시 관계가 있는 것은 아닙니다 이변량 분석의 장점: - 관계의 존재 여부를 객관적으로 판단할 수 있습니다 - 관계의 방향(양의 관계, 음의 관계)을 알 수 있습니다 - 관계의 강도를 숫자로 표현하여 비교할 수 있습니다 실제 동작 원리 1단계: 두 변수의 데이터를 짝지어 모읍니다.
예를 들어, 각 학생의 공부 시간과 그 학생의 시험 점수를 함께 기록합니다. 2단계: 한 변수가 평균보다 클 때, 다른 변수도 평균보다 큰지 확인합니다.
3단계: 이런 패턴이 일관되게 나타나면 두 변수 사이에 관계가 있다고 판단합니다. 실무 활용 예시 온라인 쇼핑몰에서 고객의 체류 시간과 구매 금액 사이의 관계를 분석할 수 있습니다.
만약 양의 관계가 있다면, 체류 시간을 늘리는 전략이 매출 향상에 도움이 될 것입니다. 주의사항 상관관계가 인과관계를 의미하지는 않습니다.
아이스크림 판매와 익사 사고가 함께 늘어나지만, 아이스크림이 익사를 유발하는 것은 아닙니다. 둘 다 여름철에 증가하는 것뿐입니다.
실전 팁
💡 분석 전에 항상 산점도를 먼저 그려서 관계의 모양을 눈으로 확인하세요
💡 이상치(극단적인 값)가 있으면 관계가 왜곡될 수 있으니 데이터를 먼저 점검하세요
2. 산점도_시각화
숫자로만 가득한 엑셀 시트를 보면서 "이 두 변수가 관계가 있을까?"라고 고민해본 적 있으신가요? 아무리 숫자를 들여다봐도 명확한 답이 나오지 않는 경험 말이에요.
사람의 뇌는 숫자보다 그림을 훨씬 빠르게 이해합니다. 1000개의 숫자를 나열하는 것보다 하나의 그래프가 더 많은 정보를 전달할 수 있죠.
바로 이럴 때 산점도가 빛을 발합니다. 두 변수의 관계를 한눈에 파악할 수 있게 해주는 강력한 시각화 도구입니다.
산점도는 두 변수의 값을 x축과 y축에 각각 표시하여 점으로 나타낸 그래프입니다. 각 점 하나가 데이터 한 건을 의미하며, 점들이 모여 만드는 패턴을 통해 관계를 파악합니다.
왜 산점도가 중요할까요? 상관계수 같은 숫자만으로는 놓치는 정보가 많습니다.
예를 들어, 비선형 관계나 이상치의 존재 여부는 산점도를 그려봐야만 알 수 있습니다. 통계학자 앤스컴의 유명한 예시에서, 완전히 다른 모양의 데이터가 같은 상관계수를 가질 수 있다는 것이 증명되었습니다.
전통적으로 데이터 분석은 숫자와 표에 의존했습니다. 하지만 현대 데이터 분석에서는 시각화가 첫 번째 단계입니다.
"일단 그려보고, 그다음에 숫자를 보라"는 것이 황금률입니다. 산점도의 핵심 특징은 첫째, 관계의 방향을 즉시 알 수 있다는 점(오른쪽 위로 올라가면 양의 관계), 둘째, 관계의 강도를 점들의 밀집도로 느낄 수 있다는 점, 셋째, 선형인지 곡선인지 관계의 형태를 파악할 수 있다는 점입니다.
다음 코드를 살펴봅시다.
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# 예시 데이터 생성
np.random.seed(42)
x = np.random.randn(100) * 10 + 50
y = 2 * x + np.random.randn(100) * 10
# 산점도 그리기
plt.figure(figsize=(10, 6))
plt.scatter(x, y, alpha=0.6, color='steelblue', edgecolors='white')
plt.xlabel('변수 X (예: 광고비)', fontsize=12)
plt.ylabel('변수 Y (예: 매출)', fontsize=12)
plt.title('두 변수의 관계: 산점도', fontsize=14)
# 추세선 추가
z = np.polyfit(x, y, 1)
p = np.poly1d(z)
plt.plot(x, p(x), "r--", alpha=0.8, label='추세선')
plt.legend()
plt.show()
도입 스토리 데이터 분석가 민준은 상사에게 "광고비와 매출 사이에 상관계수가 0.85입니다"라고 보고했다. 하지만 상사는 "그래서 그게 무슨 의미야?
눈에 보이게 보여줘"라고 말했다. 민준은 산점도 하나를 그려 보여주었고, 상사는 단번에 이해했다.
산점도란? 산점도는 두 변수를 각각 x축과 y축에 놓고, 데이터를 점으로 찍어 표현한 그래프입니다. 마치 밤하늘의 별자리처럼, 점들이 모여 만드는 모양을 통해 이야기를 읽어내는 것과 같습니다.
기존 방식의 문제점: - 숫자만으로는 직관적 이해가 어려움: 상관계수 0.7이 실제로 어떤 모양인지 상상하기 어렵습니다 - 데이터의 분포를 놓침: 평균과 표준편차만으로는 데이터가 어떻게 퍼져 있는지 알 수 없습니다 - 이상치를 발견하기 어려움: 표만 봐서는 튀는 값을 찾기가 쉽지 않습니다 산점도의 장점: - 관계의 존재 여부를 즉시 파악할 수 있습니다 - 선형 관계인지, 곡선 관계인지 형태를 알 수 있습니다 - 이상치가 어디에 있는지 바로 눈에 띕니다 실제 동작 원리 1단계: 각 데이터 포인트에 대해 x값을 가로축에, y값을 세로축에 찍습니다. 2단계: 모든 데이터를 점으로 표시하면 패턴이 드러납니다.
3단계: 점들이 오른쪽 위로 향하면 양의 관계, 오른쪽 아래로 향하면 음의 관계, 흩어져 있으면 관계 없음입니다. 실무 활용 예시 부동산 분석에서 집의 크기(평수)와 가격 사이의 관계를 산점도로 그려볼 수 있습니다.
대부분 양의 관계가 보이겠지만, 입지에 따라 같은 크기여도 가격 차이가 큰 점들을 발견할 수 있습니다. 주의사항 데이터가 너무 많으면 점들이 겹쳐서 패턴을 파악하기 어려울 수 있습니다.
이때는 투명도(alpha)를 조절하거나 밀도 플롯을 사용하세요.
실전 팁
💡 항상 alpha(투명도) 값을 0.5~0.7 정도로 설정하면 겹치는 점도 보입니다
💡 추세선을 함께 그리면 전체적인 방향성을 더 쉽게 파악할 수 있습니다
3. 피어슨_상관계수
"이 두 변수가 관련이 있어 보이긴 하는데, 얼마나 관련이 있는 거지?" 산점도를 보면 대략적인 느낌은 오지만, 정확히 얼마나 강한 관계인지 말하기는 어렵습니다. 비즈니스 미팅에서 "꽤 관련 있어 보입니다"라고 말하면 설득력이 떨어집니다.
"두 변수의 상관계수는 0.85로, 매우 강한 양의 상관관계를 보입니다"라고 말하면 훨씬 전문적이죠. 바로 이럴 때 피어슨 상관계수가 필요합니다.
관계의 강도를 -1에서 1 사이의 숫자로 정확하게 표현해주는 도구입니다.
피어슨 상관계수는 두 변수 사이의 선형 관계의 강도와 방향을 -1에서 1 사이의 숫자로 나타낸 것입니다. 1에 가까우면 강한 양의 관계, -1에 가까우면 강한 음의 관계, 0에 가까우면 관계가 없음을 의미합니다.
왜 피어슨 상관계수가 필요할까요? "관계가 있다"와 "관계가 강하다"는 다른 말입니다.
상관계수를 통해 우리는 관계의 강도를 객관적인 숫자로 표현하고, 서로 다른 변수 쌍의 관계를 비교할 수 있습니다. 상관계수의 해석 기준을 알아두면 좋습니다.
절댓값이 0.1 미만이면 거의 무관계, 0.10.3이면 약한 상관, 0.30.5면 보통 상관, 0.5~0.7이면 강한 상관, 0.7 이상이면 매우 강한 상관으로 봅니다. 피어슨 상관계수의 핵심 특징은 첫째, 단위에 영향을 받지 않는다는 점(센티미터든 미터든 같은 값), 둘째, 선형 관계만 측정한다는 점, 셋째, 이상치에 민감하다는 점입니다.
다음 코드를 살펴봅시다.
import pandas as pd
import numpy as np
from scipy import stats
# 예시 데이터: 키와 몸무게
data = {
'height': [160, 165, 170, 175, 180, 185, 190],
'weight': [50, 55, 65, 70, 75, 82, 90]
}
df = pd.DataFrame(data)
# 피어슨 상관계수 계산 - 방법 1: pandas
correlation = df['height'].corr(df['weight'])
print(f"피어슨 상관계수: {correlation:.4f}")
# 피어슨 상관계수 계산 - 방법 2: scipy (p-value 포함)
corr, p_value = stats.pearsonr(df['height'], df['weight'])
print(f"상관계수: {corr:.4f}, p-value: {p_value:.4f}")
# 상관관계 해석
if abs(corr) >= 0.7:
print("매우 강한 상관관계")
elif abs(corr) >= 0.5:
print("강한 상관관계")
도입 스토리 스타트업의 데이터팀장 소연은 투자자 미팅을 준비하고 있었다. "고객 만족도와 재구매율이 관련 있다"는 것을 보여줘야 했는데, 그냥 "관련 있습니다"라고 말하기엔 부족했다.
그녀는 상관계수 0.82라는 숫자를 제시했고, 투자자들은 고개를 끄덕였다. 피어슨 상관계수란? 피어슨 상관계수는 두 변수가 얼마나 함께 움직이는지를 -1에서 1 사이의 숫자로 표현한 것입니다.
마치 두 사람이 얼마나 발걸음을 맞춰 걷는지를 점수로 매기는 것과 같습니다. 완벽하게 맞추면 1점, 완전 반대로 걸으면 -1점입니다.
기존 방식의 문제점: - 주관적 판단: "관계가 있어 보인다"는 사람마다 기준이 다릅니다 - 비교 불가능: 여러 변수 쌍 중 어느 것이 더 강한 관계인지 말하기 어렵습니다 - 커뮤니케이션 어려움: 비전문가에게 관계의 강도를 설명하기 어렵습니다 피어슨 상관계수의 장점: - 객관적인 숫자로 표현되어 누구나 같은 기준으로 해석합니다 - 서로 다른 변수 쌍을 비교할 수 있습니다 - 통계적 유의성을 p-value로 검증할 수 있습니다 실제 동작 원리 1단계: 각 변수에서 평균을 빼서 중심화합니다. 이렇게 하면 평균이 0이 됩니다.
2단계: 두 변수의 중심화된 값을 곱하여 공분산을 구합니다. 같은 방향으로 움직이면 양수, 반대면 음수가 됩니다.
3단계: 공분산을 각 변수의 표준편차로 나누어 정규화합니다. 이렇게 하면 -1에서 1 사이의 값이 됩니다.
실무 활용 예시 금융 분야에서 두 주식의 상관계수를 계산하여 포트폴리오를 구성합니다. 상관계수가 낮은 주식들을 섞으면 위험을 분산할 수 있습니다.
만약 A주식과 B주식의 상관계수가 0.9라면, 둘 다 같이 오르내리므로 분산 효과가 적습니다. 주의사항 피어슨 상관계수는 선형 관계만 측정합니다.
U자 형태의 곡선 관계가 있어도 상관계수는 0에 가깝게 나올 수 있습니다. 항상 산점도와 함께 확인하세요.
실전 팁
💡 상관계수가 높아도 반드시 인과관계를 의미하지는 않습니다
💡 p-value가 0.05 미만인지 확인하여 통계적으로 유의미한지 검증하세요
4. 스피어만_순위_상관계수
설문조사에서 "매우 불만족=1, 불만족=2, 보통=3, 만족=4, 매우 만족=5"처럼 순위형 데이터를 다룬 적 있으신가요? 이런 데이터에 피어슨 상관계수를 쓰면 정확하지 않을 수 있습니다.
피어슨 상관계수는 데이터가 정규분포를 따르고 선형 관계일 때 가장 정확합니다. 하지만 현실의 데이터는 항상 그렇게 예쁘게 생기지 않았죠.
바로 이럴 때 스피어만 순위 상관계수가 필요합니다. 원래 값 대신 순위를 사용해서 더 넓은 범위의 데이터에 적용할 수 있는 방법입니다.
스피어만 순위 상관계수는 데이터의 실제 값 대신 순위를 사용하여 상관관계를 계산합니다. 원본 데이터를 크기 순으로 순위를 매긴 후, 그 순위에 대해 피어슨 상관계수를 구하는 방식입니다.
왜 스피어만이 필요할까요? 피어슨은 이상치에 매우 민감합니다.
데이터 중 하나가 극단적으로 크면 상관계수가 크게 왜곡될 수 있습니다. 반면 스피어만은 순위만 보기 때문에 이상치의 영향을 덜 받습니다.
100이든 1000이든 1등은 1등이니까요. 또한 스피어만은 비선형적이지만 단조로운 관계도 잡아냅니다.
예를 들어, x가 증가할 때 y도 항상 증가하지만 그 증가폭이 일정하지 않은 경우에도 스피어만은 높은 값을 보입니다. 스피어만의 핵심 특징은 첫째, 이상치에 강건하다는 점, 둘째, 순서형 데이터에 적합하다는 점, 셋째, 단조 관계를 측정한다는 점입니다.
다음 코드를 살펴봅시다.
import pandas as pd
import numpy as np
from scipy import stats
# 예시: 고객 만족도(순위형)와 재구매 의향(순위형)
data = {
'satisfaction': [1, 2, 2, 3, 4, 4, 5, 5], # 1-5 척도
'repurchase': [1, 2, 1, 3, 4, 5, 5, 4] # 1-5 척도
}
df = pd.DataFrame(data)
# 스피어만 상관계수 계산
spearman_corr, p_value = stats.spearmanr(df['satisfaction'], df['repurchase'])
print(f"스피어만 상관계수: {spearman_corr:.4f}")
print(f"p-value: {p_value:.4f}")
# 피어슨과 비교
pearson_corr, _ = stats.pearsonr(df['satisfaction'], df['repurchase'])
print(f"피어슨 상관계수: {pearson_corr:.4f}")
# 이상치가 있는 경우 비교
data_outlier = {'x': [1, 2, 3, 4, 5, 100], 'y': [2, 4, 6, 8, 10, 12]}
print(f"\n이상치 포함 - 피어슨: {stats.pearsonr(data_outlier['x'], data_outlier['y'])[0]:.4f}")
print(f"이상치 포함 - 스피어만: {stats.spearmanr(data_outlier['x'], data_outlier['y'])[0]:.4f}")
도입 스토리 연구원 태희는 설문조사 데이터를 분석하고 있었다. 학력(고졸, 대졸, 석사, 박사)과 연봉 만족도(1-5점) 사이의 관계를 보려고 피어슨을 썼는데, 결과가 이상했다.
선배가 "그 데이터는 순서형이니까 스피어만을 써봐"라고 조언했고, 훨씬 의미 있는 결과가 나왔다. 스피어만 순위 상관계수란? 스피어만 상관계수는 데이터의 실제 숫자 대신 "몇 등인지"로 관계를 측정합니다.
마치 달리기 대회에서 기록(초) 대신 순위(1등, 2등...)로 실력을 비교하는 것과 같습니다. 기록 차이가 크든 작든, 순위가 같으면 같은 대우를 받습니다.
기존 방식의 문제점: - 피어슨은 이상치에 민감: 한 명의 극단적인 값이 전체 결과를 왜곡합니다 - 순서형 데이터에 부적절: "매우 만족"이 "만족"보다 정확히 몇 배 좋은지 알 수 없습니다 - 비선형 단조 관계를 놓침: 함께 증가하지만 일정하지 않은 관계를 잡지 못합니다 스피어만의 장점: - 이상치의 영향을 최소화합니다 - 순서형 데이터(리커트 척도 등)에 적합합니다 - 데이터가 정규분포가 아니어도 사용할 수 있습니다 실제 동작 원리 1단계: 각 변수의 값을 크기 순으로 순위를 매깁니다. [10, 30, 20]은 [1등, 3등, 2등]이 됩니다.
2단계: 원래 값 대신 순위 값으로 데이터를 대체합니다. 3단계: 순위 데이터에 대해 피어슨 상관계수를 계산합니다.
실무 활용 예시 호텔 리뷰 분석에서 객실 청결도 점수(1-5)와 전체 만족도(1-5) 사이의 관계를 분석할 때 스피어만이 적합합니다. 1점과 2점의 차이가 4점과 5점의 차이와 같다고 보기 어렵기 때문입니다.
주의사항 스피어만도 완벽하지 않습니다. 동점(같은 값)이 많으면 순위를 매기기 어려워지고, 정확도가 떨어질 수 있습니다.
실전 팁
💡 데이터에 이상치가 의심되면 스피어만을 먼저 시도해보세요
💡 리커트 척도(1-5점, 1-7점 등) 설문 데이터에는 스피어만이 더 적합합니다
5. 교차분석_카이제곱검정
"남자와 여자 중 누가 더 아이폰을 선호할까?" 또는 "학력에 따라 선호하는 브랜드가 다를까?" 이런 질문을 데이터로 답하려면 어떻게 해야 할까요? 지금까지 배운 상관계수는 연속적인 숫자 데이터(키, 몸무게, 점수 등)에 사용합니다.
하지만 성별, 지역, 브랜드처럼 범주형 데이터 사이의 관계는 어떻게 분석할까요? 바로 이럴 때 교차분석과 카이제곱 검정이 필요합니다.
범주형 변수들 사이의 관계를 분석하는 강력한 도구입니다.
교차분석은 두 개의 범주형 변수를 행과 열에 배치하여 각 조합의 빈도를 표로 정리한 것입니다. 이 표를 교차표 또는 분할표라고 부릅니다.
카이제곱 검정은 이 교차표에서 두 변수가 독립인지(관계가 없는지) 통계적으로 검증합니다. 왜 교차분석이 필요할까요?
마케팅에서 타겟 고객을 정할 때, 의학에서 위험 요인을 찾을 때, 사회과학에서 집단 간 차이를 비교할 때 모두 범주형 데이터를 다룹니다. 상관계수로는 분석할 수 없는 영역입니다.
카이제곱 검정의 원리는 간단합니다. "만약 두 변수가 관계가 없다면 기대되는 빈도"와 "실제 관측된 빈도"를 비교합니다.
차이가 크면 관계가 있다고 판단합니다. 교차분석의 핵심 특징은 첫째, 범주형 데이터에 특화되어 있다는 점, 둘째, 시각적으로 이해하기 쉬운 표 형태라는 점, 셋째, 카이제곱 통계량으로 통계적 유의성을 검증할 수 있다는 점입니다.
다음 코드를 살펴봅시다.
import pandas as pd
import numpy as np
from scipy import stats
# 예시: 성별과 제품 선호도
data = {
'gender': ['남', '남', '남', '여', '여', '여', '남', '여', '남', '여'] * 10,
'preference': ['A', 'B', 'A', 'B', 'B', 'A', 'A', 'B', 'B', 'A'] * 10
}
df = pd.DataFrame(data)
# 교차표 생성
crosstab = pd.crosstab(df['gender'], df['preference'])
print("교차표:")
print(crosstab)
# 카이제곱 검정
chi2, p_value, dof, expected = stats.chi2_contingency(crosstab)
print(f"\n카이제곱 통계량: {chi2:.4f}")
print(f"p-value: {p_value:.4f}")
print(f"자유도: {dof}")
# 기대빈도
print(f"\n기대빈도:")
print(pd.DataFrame(expected, index=crosstab.index, columns=crosstab.columns))
도입 스토리 마케터 준영은 새 광고 캠페인을 기획하고 있었다. 20대와 40대 중 어느 연령대가 프리미엄 제품을 더 선호하는지 알아야 했다.
나이는 숫자지만 연령대는 범주다. 상관계수를 쓸 수 없어서 고민하다가 교차분석을 알게 되었다.
교차분석이란? 교차분석은 두 범주형 변수의 조합별로 몇 명인지 세어서 표로 만드는 것입니다. 마치 학교에서 반별, 성별로 학생 수를 정리한 표와 같습니다.
이 표를 보면 어떤 조합이 많은지, 패턴이 있는지 한눈에 알 수 있습니다. 기존 방식의 문제점: - 상관계수는 범주형에 사용 불가: 성별을 1, 2로 바꿔서 계산하면 의미가 왜곡됩니다 - 단순 비율만으로는 부족: "남자의 60%가 A를 선호"만으로는 여자와 비교가 어렵습니다 - 우연인지 실제 차이인지 구분 불가: 표본에서의 차이가 모집단에서도 존재하는지 알 수 없습니다 카이제곱 검정의 장점: - 범주형 데이터 간의 관계를 분석할 수 있습니다 - 통계적 유의성을 검증하여 우연을 배제합니다 - 기대빈도와 비교하여 어떤 조합이 특이한지 알 수 있습니다 실제 동작 원리 1단계: 두 변수의 모든 조합에 대해 실제 빈도를 셉니다 (관측빈도).
2단계: "두 변수가 독립이라면" 기대되는 빈도를 계산합니다 (기대빈도). 3단계: 관측빈도와 기대빈도의 차이를 합산하여 카이제곱 통계량을 구합니다.
차이가 클수록 두 변수는 관계가 있습니다. 실무 활용 예시 병원에서 흡연 여부(흡연/비흡연)와 폐 질환 여부(있음/없음)의 관계를 분석할 수 있습니다.
카이제곱 검정 결과 p-value가 0.05 미만이면, 흡연과 폐 질환 사이에 통계적으로 유의미한 관계가 있다고 결론 내릴 수 있습니다. 주의사항 기대빈도가 5 미만인 셀이 많으면 카이제곱 검정의 정확도가 떨어집니다.
이런 경우 피셔의 정확 검정을 사용하세요.
실전 팁
💡 교차표를 만들 때는 pd.crosstab()이 가장 간편합니다
💡 기대빈도가 5 미만인 셀이 전체의 20%를 넘으면 피셔 정확 검정을 고려하세요
6. 히트맵_상관행렬
변수가 10개, 20개, 심지어 100개인 데이터셋에서 어떤 변수들이 서로 관련 있는지 어떻게 파악할 수 있을까요? 일일이 산점도를 그리면 100개의 변수에 대해 4,950개의 그래프를 그려야 합니다.
모든 변수 쌍의 상관계수를 표로 정리하면 숫자가 너무 많아서 패턴을 찾기 어렵습니다. 눈이 아파오기 시작하죠.
바로 이럴 때 상관행렬 히트맵이 빛을 발합니다. 색깔의 진하기로 상관관계의 강도를 표현하여, 수백 개의 관계를 한 눈에 파악할 수 있게 해줍니다.
상관행렬은 모든 변수 쌍의 상관계수를 행렬 형태로 정리한 것입니다. 히트맵은 이 숫자들을 색깔로 변환하여 시각화합니다.
진한 빨강은 강한 양의 상관, 진한 파랑은 강한 음의 상관, 흰색에 가까우면 상관없음을 나타냅니다. 왜 히트맵이 필요할까요?
머신러닝에서 변수 선택을 할 때, 서로 너무 상관이 높은 변수들을 함께 사용하면 다중공선성 문제가 생깁니다. 히트맵으로 빠르게 이런 변수들을 찾아낼 수 있습니다.
상관행렬의 특징을 알아두면 좋습니다. 첫째, 대각선은 항상 1입니다(자기 자신과의 상관).
둘째, 대각선을 기준으로 대칭입니다(A와 B의 상관 = B와 A의 상관). 셋째, 색깔 패턴으로 변수들의 군집을 발견할 수 있습니다.
다음 코드를 살펴봅시다.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 예시 데이터: 학생 성적
np.random.seed(42)
n = 100
data = {
'math': np.random.randn(n) * 15 + 70,
'physics': np.random.randn(n) * 15 + 70,
'korean': np.random.randn(n) * 10 + 75,
'english': np.random.randn(n) * 12 + 72,
'history': np.random.randn(n) * 10 + 78
}
# 수학과 물리는 상관관계 높게 설정
data['physics'] = data['math'] * 0.8 + np.random.randn(n) * 5
df = pd.DataFrame(data)
# 상관행렬 계산
corr_matrix = df.corr()
print("상관행렬:")
print(corr_matrix.round(2))
# 히트맵 시각화
plt.figure(figsize=(10, 8))
sns.heatmap(corr_matrix, annot=True, cmap='RdBu_r', center=0,
vmin=-1, vmax=1, square=True, fmt='.2f')
plt.title('과목별 성적 상관관계 히트맵')
plt.tight_layout()
plt.show()
도입 스토리 데이터 사이언티스트 하은은 50개의 변수가 있는 데이터를 받았다. 어떤 변수들이 타겟과 관련 있는지, 어떤 변수들끼리 중복되는 정보를 담고 있는지 파악해야 했다.
일일이 비교하기엔 1,225개의 조합이었다. 히트맵 하나로 10분 만에 전체 그림을 파악했다.
상관행렬 히트맵이란? 상관행렬 히트맵은 모든 변수 쌍의 상관계수를 색깔로 표현한 그림입니다. 마치 열화상 카메라로 건물을 찍으면 따뜻한 곳은 빨갛고 차가운 곳은 파랗게 보이는 것처럼, 상관이 높으면 진한 색, 없으면 연한 색으로 표시됩니다.
기존 방식의 문제점: - 숫자만으로는 패턴 파악이 어려움: 상관행렬 표를 눈으로 읽기가 힘듭니다 - 변수가 많으면 비교 불가능: 50개 변수의 1,225개 조합을 일일이 볼 수 없습니다 - 변수 군집을 발견하기 어려움: 비슷한 특성의 변수들을 찾기가 어렵습니다 히트맵의 장점: - 전체 상관관계 구조를 한눈에 파악합니다 - 강한 상관을 가진 변수 쌍을 빠르게 발견합니다 - 변수들의 군집(클러스터)을 시각적으로 확인합니다 실제 동작 원리 1단계: 모든 변수 쌍에 대해 상관계수를 계산하여 행렬을 만듭니다. 2단계: 상관계수 값을 색깔에 매핑합니다.
보통 양의 상관은 빨강, 음의 상관은 파랑을 사용합니다. 3단계: 각 셀을 해당 색깔로 채워 그리드 형태의 히트맵을 완성합니다.
실무 활용 예시 주식 포트폴리오를 구성할 때, 여러 종목의 수익률 상관관계를 히트맵으로 확인합니다. 서로 상관이 낮은 종목들을 선택하면 위험을 분산할 수 있습니다.
히트맵에서 진한 빨간 블록이 보이면 그 종목들은 함께 움직인다는 의미입니다. 주의사항 히트맵의 색깔 범위(vmin, vmax)를 -1에서 1로 고정하지 않으면 약한 상관도 진하게 보일 수 있습니다.
항상 색깔 범위를 확인하세요.
실전 팁
💡 cmap='RdBu_r'과 center=0을 사용하면 양수/음수 상관을 직관적으로 구분할 수 있습니다
💡 annot=True로 설정하면 각 셀에 상관계수 숫자가 표시됩니다
7. 회귀선_추가
산점도에서 점들이 대충 오른쪽 위로 향하는 것 같긴 한데, 정확히 어떤 관계인지 말하기 어려울 때가 있습니다. "대충 이런 방향"이라고 손으로 선을 그어볼 수는 있지만, 그건 주관적이죠.
만약 "x가 1 증가하면 y가 평균적으로 2.5 증가한다"처럼 정확한 관계식을 알 수 있다면 얼마나 좋을까요? 예측도 할 수 있고, 영향력의 크기도 알 수 있을 것입니다.
바로 이럴 때 회귀선이 필요합니다. 데이터에 가장 잘 맞는 직선을 찾아, 두 변수의 관계를 수학적으로 표현해줍니다.
회귀선은 산점도의 점들을 가장 잘 대표하는 직선입니다. 수학적으로 말하면, 모든 점에서 선까지의 수직 거리의 제곱합이 최소가 되는 선입니다.
이것을 최소제곱법이라고 합니다. 회귀선의 방정식은 y = ax + b 형태입니다.
여기서 a는 기울기로, x가 1 증가할 때 y가 평균적으로 얼마나 변하는지를 나타냅니다. b는 절편으로, x가 0일 때의 y 값입니다.
왜 회귀선이 중요할까요? 첫째, 예측에 사용할 수 있습니다.
광고비가 100만원이면 매출이 얼마일지 추정할 수 있습니다. 둘째, 영향력을 정량화합니다.
"광고비 1만원당 매출 5만원 증가"처럼 명확한 해석이 가능합니다. 회귀선의 핵심 특징은 첫째, 데이터의 전반적인 추세를 한 줄로 요약한다는 점, 둘째, 기울기로 영향력의 크기와 방향을 알 수 있다는 점, 셋째, 새로운 x 값에 대한 y를 예측할 수 있다는 점입니다.
다음 코드를 살펴봅시다.
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
import pandas as pd
# 예시: 광고비와 매출
np.random.seed(42)
ad_budget = np.array([10, 20, 30, 40, 50, 60, 70, 80, 90, 100])
sales = 5 * ad_budget + np.random.randn(10) * 30 + 100
# 선형 회귀 계산
slope, intercept, r_value, p_value, std_err = stats.linregress(ad_budget, sales)
print(f"회귀식: 매출 = {slope:.2f} × 광고비 + {intercept:.2f}")
print(f"기울기(slope): {slope:.2f} - 광고비 1만원당 매출 {slope:.2f}만원 증가")
print(f"R-squared: {r_value**2:.4f} - 설명력 {r_value**2*100:.1f}%")
# 시각화
plt.figure(figsize=(10, 6))
plt.scatter(ad_budget, sales, color='steelblue', s=100, label='실제 데이터')
plt.plot(ad_budget, slope * ad_budget + intercept, 'r-', linewidth=2, label='회귀선')
plt.xlabel('광고비 (만원)')
plt.ylabel('매출 (만원)')
plt.title('광고비와 매출의 관계')
plt.legend()
plt.show()
도입 스토리 영업팀장 수진은 내년 예산 회의를 준비하고 있었다. "광고비를 늘리면 매출이 올라요"라고 말하면 당연히 "얼마나?"라는 질문이 돌아올 것이다.
지난 3년 데이터를 분석해서 "광고비 100만원당 매출 500만원 증가"라는 정확한 숫자를 제시해야 했다. 회귀선이란? 회귀선은 데이터 점들 사이를 지나가는 "가장 좋은" 직선입니다.
마치 수많은 사람들이 걸어간 잔디밭에 자연스럽게 생기는 길처럼, 데이터가 향하는 방향을 나타냅니다. 이 선을 따라가면 한 변수의 값으로 다른 변수를 예측할 수 있습니다.
기존 방식의 문제점: - 눈대중으로 선을 그으면 주관적: 사람마다 다른 선을 그립니다 - 정확한 관계식을 알 수 없음: "대충 비례한다" 이상의 정보를 얻기 어렵습니다 - 예측이 불가능: 새로운 상황에서 결과를 추정할 수 없습니다 회귀선의 장점: - 객관적인 기준(최소제곱법)으로 유일한 선을 찾습니다 - y = ax + b 형태의 명확한 수식을 제공합니다 - 새로운 x값에 대한 y를 예측할 수 있습니다 실제 동작 원리 1단계: 모든 데이터 점에 대해, 가능한 모든 직선을 생각합니다. 2단계: 각 점에서 직선까지의 수직 거리(잔차)를 계산합니다.
3단계: 모든 잔차의 제곱합이 가장 작은 직선을 선택합니다. 이것이 최소제곱법입니다.
실무 활용 예시 부동산 앱에서 집 크기(평수)와 가격의 관계를 회귀선으로 분석합니다. "1평당 가격이 약 3000만원"이라는 기울기를 알면, 새로운 매물의 적정 가격을 추정할 수 있습니다.
주의사항 회귀선은 데이터 범위 내에서만 신뢰할 수 있습니다. 100평까지의 데이터로 만든 회귀선으로 500평 집의 가격을 예측하면 틀릴 가능성이 높습니다.
실전 팁
💡 R-squared(결정계수)가 0.7 이상이면 회귀선의 설명력이 좋다고 볼 수 있습니다
💡 잔차(실제값 - 예측값)의 패턴을 확인하여 회귀선이 적절한지 검증하세요
8. 다중변수_페어플롯
변수가 여러 개일 때, 어떤 변수들이 서로 관련 있고, 어떤 변수가 타겟과 가장 관련이 높은지 한눈에 보고 싶을 때가 있습니다. 히트맵으로 숫자는 알 수 있지만, 실제 데이터의 분포와 관계의 모양은 보이지 않죠.
만약 모든 변수 쌍의 산점도를 한 번에 볼 수 있다면? 그리고 각 변수의 분포도 함께 볼 수 있다면?
데이터 탐색이 훨씬 효율적일 것입니다. 바로 이럴 때 페어플롯이 필요합니다.
모든 변수 쌍의 산점도를 격자 형태로 한번에 보여주는 강력한 시각화 도구입니다.
페어플롯은 데이터셋의 모든 변수 쌍에 대한 산점도를 격자 형태로 배열한 그래프입니다. 대각선에는 각 변수의 분포(히스토그램 또는 KDE)가 표시됩니다.
seaborn 라이브러리의 pairplot 함수로 쉽게 그릴 수 있습니다. 왜 페어플롯이 필요할까요?
데이터 분석의 첫 단계인 탐색적 데이터 분석(EDA)에서 가장 유용합니다. 변수들의 분포, 변수 간 관계, 이상치, 군집 등을 한 번에 파악할 수 있기 때문입니다.
페어플롯에 hue(색깔) 파라미터를 추가하면, 범주별로 다른 색깔로 점을 표시합니다. 예를 들어, 붓꽃 데이터에서 종류별로 색을 다르게 하면, 어떤 변수가 종류를 잘 구분하는지 알 수 있습니다.
다음 코드를 살펴봅시다.
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import load_iris
# 붓꽃 데이터 로드
iris = load_iris()
df = pd.DataFrame(iris.data, columns=['꽃받침길이', '꽃받침너비', '꽃잎길이', '꽃잎너비'])
df['종류'] = pd.Categorical.from_codes(iris.target, iris.target_names)
# 페어플롯 그리기
sns.pairplot(df, hue='종류', diag_kind='kde',
plot_kws={'alpha': 0.6, 's': 50},
height=2.5, aspect=1)
plt.suptitle('붓꽃 데이터 페어플롯', y=1.02)
plt.tight_layout()
plt.show()
# 특정 변수만 선택해서 그리기
selected_vars = ['꽃잎길이', '꽃잎너비', '종류']
sns.pairplot(df[selected_vars], hue='종류', diag_kind='hist')
plt.show()
도입 스토리 머신러닝 입문자 성호는 첫 분류 프로젝트를 시작했다. 4개의 특성으로 꽃의 종류를 예측해야 했는데, 어떤 특성이 중요한지 감이 오지 않았다.
선배가 "일단 페어플롯 그려봐"라고 했고, 한 장의 그림에서 꽃잎 길이와 너비가 종류를 잘 구분한다는 것을 발견했다. 페어플롯이란? 페어플롯은 여러 변수의 모든 쌍에 대해 산점도를 그리고, 대각선에는 각 변수의 분포를 보여주는 그래프입니다.
마치 여러 명의 사진을 찍을 때, 모든 2인 조합의 사진을 찍어 한 앨범에 정리한 것과 같습니다. 한눈에 누가 누구와 어울리는지 알 수 있습니다.
기존 방식의 문제점: - 산점도를 하나씩 그리면 시간이 오래 걸림: 4개 변수면 6개, 10개 변수면 45개의 그래프가 필요합니다 - 전체적인 패턴을 파악하기 어려움: 그래프가 분리되어 있으면 비교가 어렵습니다 - 범주별 차이를 보기 어려움: 그룹별로 다른 패턴이 있는지 알기 어렵습니다 페어플롯의 장점: - 모든 변수 조합을 한 번에 볼 수 있습니다 - hue 파라미터로 범주별 색깔을 다르게 하여 그룹 차이를 파악합니다 - 대각선의 분포 그래프로 각 변수의 특성도 함께 확인합니다 실제 동작 원리 1단계: n개의 변수가 있으면 n × n 크기의 격자를 만듭니다. 2단계: (i, j) 위치에는 i번째 변수와 j번째 변수의 산점도를 그립니다.
3단계: 대각선(i = j)에는 해당 변수의 분포(히스토그램 또는 밀도 그래프)를 그립니다. 실무 활용 예시 신용카드 사기 탐지에서 여러 거래 특성(금액, 시간, 빈도 등)의 페어플롯을 그리고 사기/정상을 색깔로 구분합니다.
어떤 특성 조합에서 사기 거래가 분리되는지 시각적으로 확인할 수 있습니다. 주의사항 변수가 10개를 넘어가면 페어플롯이 너무 복잡해집니다.
이런 경우 중요한 변수만 선택하거나, 히트맵을 먼저 보고 상관이 높은 변수들만 골라서 페어플롯을 그리세요.
실전 팁
💡 diag_kind='kde'로 설정하면 대각선에 부드러운 밀도 곡선이 그려집니다
💡 변수가 많으면 vars 파라미터로 원하는 변수만 선택하여 그리세요
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
범주형 변수 시각화 완벽 가이드 Bar Chart와 Count Plot
데이터 분석에서 가장 기본이 되는 범주형 변수 시각화 방법을 알아봅니다. Matplotlib의 Bar Chart부터 Seaborn의 Count Plot까지, 실무에서 바로 활용할 수 있는 시각화 기법을 배워봅니다.
단변량 분석 분포 시각화 완벽 가이드
데이터 분석의 첫걸음인 단변량 분석과 분포 시각화를 배웁니다. 히스토그램, 박스플롯, 밀도 그래프 등 다양한 시각화 방법을 초보자도 쉽게 이해할 수 있도록 설명합니다.
데이터 타입 변환 및 정규화 완벽 가이드
데이터 분석과 머신러닝에서 가장 기초가 되는 데이터 타입 변환과 정규화 기법을 배워봅니다. 실무에서 자주 마주치는 데이터 전처리 문제를 Python으로 쉽게 해결하는 방법을 알려드립니다.
이상치 탐지 및 처리 완벽 가이드
데이터 속에 숨어있는 이상한 값들을 찾아내고 처리하는 방법을 배워봅니다. 실무에서 자주 마주치는 이상치 문제를 Python으로 해결하는 다양한 기법을 소개합니다.
결측치 처리 전략 완벽 가이드
데이터 분석에서 가장 먼저 만나는 문제, 결측치! 삭제부터 고급 대체 기법까지, 실무에서 바로 쓸 수 있는 결측치 처리 전략을 초급자도 이해하기 쉽게 알려드립니다. 데이터의 품질을 높이고 정확한 분석 결과를 얻어보세요.