파이썬 pandas 상관 공분산 완벽 가이드 corr cov min_periods pairwise 옵션
📌 데이터 상관관계를 정확하게 계산하고 해석하는 법, corr와 cov의 차이부터 min_periods와 pairwise 활용까지 한 번에 정리합니다
데이터 열 간의 관계를 숫자로 확인할 때 가장 먼저 떠올리는 도구가 바로 pandas입니다.
특히 corr와 cov는 상관계수와 공분산을 손쉽게 계산해 주는 표준 함수죠.
하지만 결측치가 섞여 있거나 관측치 수가 적을 때 결과가 왜 달라지는지, 윈도우 연산에서 열 조합을 어떻게 만들지에 따라 출력 형태가 왜 바뀌는지 헷갈릴 때가 많습니다.
실무에서는 계산 방법의 기본 가정과 파라미터 뜻을 모르면 숫자만 보고 잘못된 결론을 내리기 쉽습니다.
이 글은 그런 위험을 줄이기 위해 핵심 개념과 설정 포인트를 친근하게 풀어 설명합니다.
핵심만 먼저 짚어 볼게요.
corr는 열 간 상관계수(pearson, spearman, kendall 등)를, cov는 공분산을 계산합니다.
두 함수 모두 결측치를 제외하고 열 쌍(pairwise)으로 계산하며, min_periods는 각 열 쌍이 유효한 결과를 내기 위해 필요한 최소 관측치 수를 지정합니다.
또한 Rolling이나 Expanding 윈도우에서의 pairwise 옵션은 모든 열 조합을 계산할지, 같은 이름의 열만 맞춰 계산할지를 결정해 결과 형태가 DataFrame 또는 MultiIndex DataFrame으로 달라집니다.
이러한 설정은 숫자 해석뿐 아니라 성능과 메모리에도 직접적인 영향을 줍니다.
📋 목차
🔎 상관과 공분산의 개념과 차이
상관과 공분산은 둘 다 변수 간 관계를 수치화하지만, 해석 방식과 단위가 다릅니다.
공분산은 두 변수가 함께 증가하거나 감소하는 경향을 원 단위 그대로 반영합니다.
값의 크기는 데이터 스케일에 의존하므로 절대 크기만으로 강도를 비교하기 어렵습니다.
상관계수는 공분산을 각 변수의 표준편차로 정규화해 -1에서 1 사이로 압축합니다.
크기가 1에 가까울수록 선형관계가 강하고, 0에 가까우면 선형관계가 약함을 뜻합니다.
부호는 관계의 방향을 의미합니다.
🧩 정의와 직관
공분산은 두 변수가 평균에서 얼마나 같은 방향으로 벗어나는지를 평균적으로 측정합니다.
한쪽이 평균보다 크면 다른 쪽도 평균보다 클 때 양수, 반대로 움직이면 음수입니다.
상관계수는 이 공분산을 각 변수의 변동성으로 나눠 규모 효과를 제거한 값입니다.
따라서 단위가 서로 다른 지표(예: 매출액, 방문자수)라도 상관계수로 비교가 가능합니다.
다만 상관계수는 선형관계를 측정한다는 점을 기억해야 합니다.
곡선형(비선형) 관계는 값이 낮게 나올 수 있습니다.
🔢 수식 관점의 핵심
공분산은 (xi−x̄)(yi−ȳ)의 평균이며, 표본 공분산에서는 분모가 보정값 n−1(기본 ddof=1)입니다.
상관계수는 공분산을 표준편차의 곱으로 나누어 정규화한 값입니다.
이 정규화 덕분에 스케일이 달라도 해석이 일관됩니다.
분모가 0이 되지 않도록 표준편차가 0인 열(상수열)은 상관 계산에서 유효값을 만들 수 없다는 점도 기억해 두세요.
📌 파이썬 pandas에서의 연결 고리
pandas에서는 DataFrame.corr로 상관계수 행렬을, DataFrame.cov로 공분산 행렬을 구합니다.
두 메서드는 결측치를 자동으로 제외하고 유효한 관측치만으로 계산합니다.
또한 메서드와 윈도우 연산(rolling, expanding)에는 min_periods와 pairwise 같은 옵션이 있어 데이터의 가용 구간과 열 조합 생성 방식에 영향을 줍니다.
상관은 방법 인자로 ‘pearson’ ‘spearman’ ‘kendall’을 선택할 수 있어 선형·순위 기반 해석을 유연하게 적용할 수 있습니다.
| 구분 | 공분산 cov | 상관계수 corr |
|---|---|---|
| 범위 | 제한 없음 | -1 ~ 1 |
| 단위 의존성 | 단위에 의존 | 단위 무관(정규화) |
| 해석 초점 | 공동 변동의 크기 | 선형 관계 강도·방향 |
| 민감도 | 스케일 변화에 민감 | 스케일 변화에 둔감 |
import pandas as pd
# 예시 데이터
df = pd.DataFrame({
"sales": [10, 12, 13, 16, 18, 20],
"visits": [100, 110, 120, 130, 150, 170],
"ads": [ 1, 1, 2, 2, 3, 3],
})
# 공분산과 상관행렬
cov_mat = df.cov() # 단위 의존
corr_pearson = df.corr() # 기본: pearson
corr_spearman = df.corr(method="spearman") # 순위 기반
print(cov_mat)
print(corr_pearson)
print(corr_spearman)
💎 핵심 포인트:
공분산은 스케일을 반영하므로 모델 입력 전 표준화 여부를 점검하세요.
상관계수는 비교 가능하지만 인과를 증명하지 않습니다.
단조 비선형 관계는 spearman 같은 순위 상관으로 보조 확인이 좋습니다.
💡 TIP: 단위가 큰 변수(예: 원화 매출)와 작은 변수(예: 클릭률)를 함께 해석할 때는 공분산보다 상관계수를 우선 확인하고, 필요하면 표준화(z-score) 후 공분산을 비교하면 직관이 좋아집니다.
⚠️ 주의: 결측치 처리 방식은 결과를 크게 바꿉니다.
행 삭제 또는 대치(imputation) 전에 pandas의 기본 동작(결측치 자동 제외)을 이해하고, 최소 관측치 기준은 min_periods로 명시하세요.
🧮 corr와 cov 핵심 파라미터 min_periods 이해
pandas의 corr()와 cov() 메서드는 단순히 수학 공식을 적용하는 수준을 넘어서, 결측치 처리나 유효 관측치 수 등 데이터 조건을 세밀하게 제어할 수 있습니다.
그 중심에는 바로 min_periods라는 옵션이 있습니다.
🔍 min_periods의 역할과 기본값
min_periods는 두 열 간 계산을 수행할 때 필요한 최소한의 유효 관측치 수를 지정합니다.
기본값은 1이며, 유효 데이터가 이 수보다 적으면 결과는 NaN으로 반환됩니다.
예를 들어, 한 열에 결측치가 많아 유효 쌍이 1개뿐이라면 상관계수를 계산할 수 없기 때문에 결과는 NaN이 됩니다.
이 옵션은 특히 rolling() 윈도우나 expanding()과 함께 사용할 때 중요합니다.
윈도우 내부의 관측치가 충분하지 않으면 계산이 의미가 없으므로, 일정 기준을 주어야 안정적인 결과를 얻을 수 있습니다.
import pandas as pd
import numpy as np
df = pd.DataFrame({
"A": [1, 2, np.nan, 4, 5],
"B": [2, np.nan, np.nan, 8, 10]
})
# min_periods=2 설정
result = df.corr(min_periods=2)
print(result)
위 예시에서, 각 열 조합의 유효 관측치가 2개 미만이면 결과는 NaN으로 표시됩니다.
이 덕분에 결측치가 많은 시계열에서도 과도한 추정 없이 신뢰도 높은 결과만 남길 수 있습니다.
🧠 min_periods가 중요한 이유
- ✅데이터 손실이 많은 시계열에서 유효 구간만 계산하도록 제한할 수 있습니다.
- 📊윈도우 기반 계산(rolling, expanding)에서 불완전한 구간을 자동으로 배제할 수 있습니다.
- 🧩상관/공분산 계산 시 NaN이 너무 많아 왜곡되는 문제를 예방합니다.
💬 min_periods는 계산 정확도를 높이는 안전장치입니다.
특히 금융 데이터나 로그 센서처럼 간헐적 결측이 있는 시계열에서는 이 값 설정이 분석 품질을 좌우합니다.
📌 corr와 cov의 min_periods 차이점
두 메서드 모두 min_periods를 지원하지만, 계산 대상에 따라 미묘한 차이가 있습니다.
corr()은 상관계수 계산에 필요한 유효한 (x, y) 쌍이 min_periods 미만이면 NaN을 반환하고, cov() 역시 동일한 방식으로 작동하되 ddof(보정자)가 추가로 영향을 줍니다.
| 함수 | min_periods 조건 | 추가 영향 요인 |
|---|---|---|
| corr() | 유효 쌍 수 < min_periods → NaN | method 인자(pearson, spearman, kendall) |
| cov() | 유효 쌍 수 < min_periods → NaN | ddof (보정값, 기본 1) |
💎 핵심 포인트:
윈도우 크기가 작거나 결측치가 많은 데이터는 min_periods를 기본값 1로 두면 오탐이 생길 수 있습니다.
일반적으로 3~5 이상으로 설정해 결과의 신뢰도를 높이는 것이 좋습니다.
⚙️ Rolling Expanding에서 pairwise 옵션 동작 방식
pandas의 rolling() 또는 expanding() 객체에 corr()과 cov()를 적용할 때,
결과 형태를 결정하는 중요한 인자가 바로 pairwise입니다.
이 옵션은 ‘모든 열 조합 간 계산을 수행할지’, ‘같은 위치(이름)끼리만 비교할지’를 정합니다.
🔧 pairwise의 기본값과 의미
기본적으로 pairwise=True입니다.
이 경우, pandas는 모든 열 간 조합을 만들어 각 쌍에 대해 rolling correlation 또는 covariance를 계산합니다.
결과는 MultiIndex DataFrame 형태로 반환되어, 열의 조합이 명시됩니다.
반대로 pairwise=False를 지정하면,
각 시점에서 같은 이름을 가진 열끼리만 비교합니다.
즉, 동일 위치 간의 상관 또는 공분산을 반환하므로 결과가 Series나 DataFrame으로 간결하게 나옵니다.
import pandas as pd
data = {
"A": [1, 2, 3, 4, 5],
"B": [5, 4, 3, 2, 1],
"C": [2, 3, 4, 5, 6]
}
df = pd.DataFrame(data)
# Rolling correlation
roll_corr_all = df.rolling(window=3).corr(pairwise=True)
roll_corr_each = df.rolling(window=3).corr(pairwise=False)
print("pairwise=True →", type(roll_corr_all))
print("pairwise=False →", type(roll_corr_each))
위 코드를 실행하면,
pairwise=True일 때는 열 간 조합(A-B, A-C, B-C 등)의 결과가 포함된 MultiIndex 형태가 출력되고,
False일 때는 단일 행렬 형태로 더 단순한 결과가 나옵니다.
📊 pairwise 동작 차이 시각적 이해
| 옵션 | 결과 형태 | 계산 대상 |
|---|---|---|
| pairwise=True | MultiIndex DataFrame | 모든 열 조합 |
| pairwise=False | DataFrame 또는 Series | 동일 위치 열끼리 |
💡 TIP: 시계열 데이터의 상관구조를 전체적으로 탐색하려면 pairwise=True가 유용합니다.
반면 동일 열의 이동 상관 추세만 보고 싶다면 False로 설정하는 것이 깔끔합니다.
💬 pairwise=True 설정은 대규모 DataFrame에서 메모리 사용량을 늘릴 수 있습니다.
열이 많을수록 조합 수가 급격히 증가하므로, 필요한 조합만 남기는 전처리 전략이 필요합니다.
📌 Rolling, Expanding과의 결합 팁
rolling()이나 expanding()에 pairwise를 함께 쓰면,
시간에 따라 변하는 이동 상관/공분산을 손쉽게 시각화할 수 있습니다.
금융 데이터에서는 종목 간 상관이 시간에 따라 얼마나 바뀌는지를 분석하는 데 자주 활용됩니다.
💎 핵심 포인트:
pairwise는 단순히 출력 형태를 바꾸는 옵션이 아니라,
계산 방식과 메모리 효율, 그리고 결과 해석 구조를 결정하는 핵심 설정입니다.
데이터 규모가 클수록 pairwise=False로 시작해 필요한 조합만 추가하는 접근이 안정적입니다.
🧰 결측치와 데이터 타입 처리 전략 numeric_only ddof
pandas에서 corr()와 cov()를 사용할 때,
결측치(NaN)와 비수치형 데이터가 섞여 있으면 계산 결과가 예상과 다르게 나오는 경우가 많습니다.
이때 핵심적으로 알아야 할 두 가지 인자가 바로 numeric_only와 ddof입니다.
🧹 결측치 자동 제외와 numeric_only 동작
pandas는 기본적으로 상관/공분산 계산 시 결측치를 자동으로 제외합니다.
즉, NaN을 포함한 행은 해당 열 쌍 계산에서 건너뛰게 되며, 결과는 유효한 관측치로만 산출됩니다.
또한 numeric_only=True로 지정하면 숫자형 열만 계산에 포함하고,
문자열이나 날짜 타입은 자동으로 제외됩니다.
import pandas as pd
import numpy as np
df = pd.DataFrame({
"A": [1, 2, np.nan, 4],
"B": [2, 4, 6, np.nan],
"C": ["x", "y", "z", "w"]
})
print(df.corr(numeric_only=True))
위 코드에서는 A와 B만 포함된 상관행렬이 계산되고,
문자열 데이터인 C는 자동으로 무시됩니다.
numeric_only=False로 설정하면 비수치형 데이터 포함 시 오류가 발생할 수 있습니다.
📏 ddof의 의미와 분모 보정
공분산을 계산할 때는 표본의 자유도를 반영하기 위해 분모를 N – ddof로 나눕니다.
기본값은 ddof=1이며, 이는 표본 공분산(sample covariance)을 계산합니다.
만약 ddof=0으로 설정하면 모집단 공분산(population covariance)을 계산하게 됩니다.
| ddof 값 | 의미 | 적용 상황 |
|---|---|---|
| 1 | 표본 공분산 (기본값) | 데이터가 모집단의 일부일 때 |
| 0 | 모집단 공분산 | 전체 데이터가 모집단일 때 |
💡 TIP: 통계 분석에서 대부분은 ddof=1을 유지합니다.
하지만 머신러닝 피처 스케일링 등에서는 전체 데이터를 기반으로 할 때 ddof=0이 더 적절할 수 있습니다.
💬 numeric_only=True는 안전하고 직관적인 설정이지만,
데이터프레임에 숫자형 외 열이 포함되어 있지 않다면 굳이 명시하지 않아도 됩니다.
ddof는 결과 스케일에 영향을 주므로, 샘플 기반 통계와 모델 기반 예측의 차이를 이해하고 선택하세요.
💎 핵심 포인트:
결측치는 자동으로 제외되지만, 데이터의 크기와 구조를 미리 확인하지 않으면 일부 열 간 결과가 NaN으로 채워질 수 있습니다.
분석 전 df.info()나 df.isna().sum()으로 데이터 상태를 점검하는 습관이 중요합니다.
🧭 해석과 시각화 모범 패턴 상관행렬 공분산행렬
상관계수와 공분산은 계산 자체보다 어떻게 해석하고 시각화하느냐가 더 중요합니다.
숫자만 나열된 행렬보다 패턴과 관계를 직관적으로 보여주는 시각화는 데이터 이해도를 높여줍니다.
pandas로 계산한 corr() 또는 cov() 결과는 seaborn, matplotlib, plotly와 함께 시각화하면 훨씬 풍부한 분석이 가능합니다.
📊 상관행렬 시각화 예시
상관행렬은 변수 간의 관계 방향과 강도를 한눈에 보여주는 대표적인 도구입니다.
색상이 짙을수록 강한 상관, 옅을수록 약한 상관을 의미하며, 음수일 경우 반비례 관계를 뜻합니다.
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
df = pd.DataFrame({
"sales": [100, 120, 140, 160, 180, 200],
"visits": [30, 35, 40, 50, 60, 70],
"ads": [5, 6, 6, 7, 8, 10]
})
corr = df.corr()
plt.figure(figsize=(6, 4))
sns.heatmap(corr, annot=True, cmap="YlGnBu", fmt=".2f")
plt.title("Correlation Matrix")
plt.show()
이 예시처럼 sns.heatmap()을 활용하면 데이터 간 관계를 시각적으로 직관적으로 파악할 수 있습니다.
특히 피처 간 다중공선성(multicollinearity)을 조기 탐지할 때 매우 유용합니다.
📈 공분산행렬 해석 요령
공분산행렬은 단위 의존적인 지표이므로, 각 변수의 스케일을 고려한 해석이 필요합니다.
양의 공분산은 두 변수가 같은 방향으로 움직임을, 음의 공분산은 반대 방향을 뜻합니다.
값이 클수록 변동 폭이 크며, 상관계수보다 데이터의 실제 분포 변화를 더 직접적으로 반영합니다.
| 값 | 해석 |
|---|---|
| 양수 | 두 변수가 함께 증가하는 경향 |
| 음수 | 한 변수가 증가할 때 다른 변수가 감소하는 경향 |
| 0 근처 | 거의 독립적이거나 비선형 관계 |
💡 TIP: 공분산행렬은 단위가 다르면 직접 비교가 어렵습니다.
표준화를 통해 단위를 맞춘 뒤 해석하거나, 상관계수를 함께 병행해 보는 것이 좋습니다.
💬 상관행렬은 패턴 파악에, 공분산행렬은 실제 분산 구조 이해에 강점을 가집니다.
두 지표를 함께 보면 데이터 간 연관성과 변동 구조를 균형 있게 분석할 수 있습니다.
💎 핵심 포인트:
corr()는 스케일이 다른 데이터 비교에 적합하고, cov()는 실제 단위 변동을 파악할 때 유용합니다.
시각화 단계에서는 두 행렬을 병렬로 표시하면 관계의 방향성과 크기를 한눈에 볼 수 있습니다.
❓ 자주 묻는 질문 (FAQ)
corr()와 cov()는 어떤 상황에서 각각 써야 하나요?
예를 들어, 두 지표가 단위가 다를 때는 corr()이 더 적합합니다.
min_periods를 지정하지 않으면 어떤 값이 기본인가요?
즉, 한 쌍의 유효한 데이터만 있어도 계산이 수행됩니다.
하지만 신뢰도를 위해 3~5 이상의 관측치를 요구하는 것이 권장됩니다.
pairwise=True와 False의 가장 큰 차이는 무엇인가요?
데이터 크기가 클 경우 pairwise=False가 속도와 메모리 효율이 더 좋습니다.
rolling().corr()을 사용할 때 NaN이 자주 생기는 이유는?
결측치를 미리 보정하거나 min_periods를 낮추면 개선됩니다.
numeric_only=True는 꼭 지정해야 하나요?
하지만 문자열이나 날짜형 열이 섞여 있다면 True로 설정해야 오류 없이 계산됩니다.
ddof는 언제 조정해야 하나요?
통계분석에서는 대부분 ddof=1이 표준입니다.
corr() 계산 결과가 NaN인 이유는 무엇인가요?
데이터의 변동성이 있는지 확인해야 합니다.
상관계수로 인과관계를 판단할 수 있나요?
상관은 단지 두 변수 간의 선형적 관계를 나타낼 뿐, 인과를 증명하지는 못합니다.
추가적인 통계 검정이나 실험 설계가 필요합니다.
🧾 pandas corr·cov 완전 정리 및 실전 활용 포인트
pandas의 corr()와 cov()는 데이터 간 관계를 수치적으로 파악하는 핵심 도구입니다.
corr()는 단위에 영향을 받지 않기 때문에 서로 다른 규모의 데이터를 비교하기에 적합하고, cov()는 실제 단위 변동을 분석할 때 효과적입니다.
또한 min_periods, pairwise, numeric_only, ddof 같은 인자들은 계산 정확도와 효율성을 조절하는 핵심 옵션이므로 반드시 숙지해야 합니다.
실무에서는 이 함수들을 단독으로 쓰기보다 rolling이나 expanding 같은 윈도우 객체, 혹은 seaborn heatmap과 함께 시각화에 활용하는 방식이 일반적입니다.
이렇게 하면 단순 수치 비교를 넘어, 시간에 따른 추세나 패턴까지도 직관적으로 이해할 수 있습니다.
💎 핵심 요약:
corr은 상관관계의 방향과 강도를, cov는 공동 변동의 절대 크기를 보여줍니다.
pairwise는 계산 조합을, min_periods는 신뢰도를, ddof는 통계적 해석 방식을 결정합니다.
데이터 분석에서 이 네 가지 옵션을 적절히 조합하면 훨씬 정확하고 풍부한 인사이트를 얻을 수 있습니다.
🏷️ 관련 태그 : pandas, 파이썬데이터분석, corr, cov, 상관계수, 공분산, min_periods, pairwise, 데이터시각화, 통계기초