Pandas 기초 데이터 분석 (공분산, 상관계수, 산점도, 추세선, 결정계수)

빠르게 여러 컬럼 간 정보를 보고싶을 때가 있다.
예를들어 엑셀에서는 이런 차트를 기본으로 제공해주기 때문에 분석이 용이하다.

엑셀에서도 간단히 되는게 Python에서 간단히 안될리가 없다.
물론 Python에서도 쉽게 결과를 얻을 수 있다.

다룰 것은 다음과 같다.

  • 공분산 (Covariance)
  • 상관계수 (Correlation)
  • 산점도 (Scatter)
  • 추세선 (Trend)
  • 결정계수 (R-squared, R^2)

Dataframe dtype

수치 계산에 들어가기 앞서 Pandas의 Dataframe의 자료형에 대한 이해가 필요하다.
보통 Dataframe을 만들면서 dtype을 지정하지 않을텐데, 자칫하다 컬럼이 ‘object’형으로 지정될 수 있다.
이게 Plot을 그릴 땐 문제가 되진 않지만, 계산을 할 때는 문제가 생긴다.
이에 Dataframe의 컬럼에 자료형을 지정해주어야 한다.

예를들어 다음과 같은 방법으로 Dataframe의 모든 컬럼에 float 자료형을 지정해줄 수 있다. [Docs]

df = pd.DataFrame(column=['a', 'b', 'c'], dtype='float')

Docs에도 나와있듯이 이 방법은 모든 컬럼을 하나의 자료형으로 바꾸어준다.
만약 각 컬럼을 원하는 자료형으로 바꾸고 싶은 경우에는 귀찮아도 아래의 방법으로 일일이 바꿔줘야한다. [Docs]

df.astype('float')
df.astype({'a': 'float', 'b': 'int32', 'c': 'category'})

Covariance

공분산 계산은 단순하다. [Docs]

df.cov()

공분산은 두 변수간 편차 곱의 평균으로 표현된다.
다시말해 한 변수만을 사용하여 공분산을 구하면 그게 곧 분산이다. (Cov(X,X) = E[(X-\mu)(X-\mu)] = \sigma^2)
문제는 편차가 정규화되지 않았기 때문에 scale에 민감하다는 것이다.
이를 보완하고자 나온 것이 다음에 소개할 상관계수(Correlation)로, 공분산을 각 확률변수의 표준편차로 나누어준 것이다.

Correlation

흔히 사용되는 Correlation로는 Pearson과 Kendall, Spearman이 있다.
Default는 Pearson이며, 만약 방법을 지정하고싶다면 method=’kendall’과 같이 지정해줄 수 있다.
만약 커스텀 Correlation을 구하고싶다면 커스텀 함수를 만들어 method로 지정해주면 된다. [Docs]

Correlation를 계산하는 방법은 세 가지이다.

  • 한 컬럼과 다른 모든 컬럼들의 Correlation (corrwith)
  • 두 컬럼 간의 Correlation (corr)
  • 모든 컬럼간의 Correlation (corr)

어쨋든 결과는 모두 동일하다.
어떤 결과만을 표시할지의 문제이다.

df.corrwith(df['avg'], method='spearman') # 'avg' 컬럼과 다른 모든 컬럼간의 Spearman Rank Correlation
df['avg'].corr(df[5], method='kendall') # 'avg' 컬럼과 5 컬럼 간의 Kentall Tau Correlation
df.corr(method='pearson') # 모든 컬럼 간의 Pearson Correlation

아래는 df.corr를 통한 모든 컬럼 간의 Correlation이다.

만약 결과를 Heatmap으로 보고싶다면 seaborn 패키지를 활용할 수 있다.

import seaborn as sb
sb.heatmap(data = df.corr(), annot=True, fmt = '.2f', linewidths=.5, cmap='Blues')

cmap이나 annotation, 크기 등은 Docs를 보며 적절히 수정해주면 된다.
다음은 실행 결과이다.

아래와 같은 응용도 가능하다.

mask = np.zeros_like(df.corr())
mask[np.triu_indices_from(mask)] = True
plt.rcParams["figure.figsize"] = (10,6) # 그림 크기 조정
sb.heatmap(data = df.corr(), mask=mask, annot=True, fmt = '.3f', linewidths=0, cmap='Greens')

Scatter Plot

Pandas Dataframe에서 특정한 두 컬럼을 x축, y축으로 설정하여 Scatter Plot을 그리는 방법이다.
필자는 ‘avg’ 컬럼을 x축으로, 5 컬럼을 y축으로 사용하였다.

import matplotlib.pyplot as plt
dataframe.plot(kind='scatter',x='avg',y=5)
plt.show()

Trend Line

numpy 패키지의 polyfit 함수를 통해 직선을 주어진 점에 fitting한다.
polyfit은 fitting 후 weight를 반환한다. [Docs]
그리고 poly1d는 weight를 이용해 1차함수를 반환한다. [Docs]

import numpy as np
df.plot(kind='scatter', x='avg', y=5)
fit_weight = np.polyfit(df['avg'], df[5], 1) # 'avg' 컬럼을 x값으로, 5 컬럼을 y값으로 하여 1차식으로 피팅한다.
trend_f = np.poly1d(fit_weight)
              
plt.plot(df['avg'], trend_f(df['avg']),"r-")
plt.title("y={:.6f}x+({:.6f})".format(fit_weight[0], fit_weight[1]))
plt.show()

R-square

R2를 계산하기 위해서는 데이터와 예측값이 필요하다.
위의 경우 사용할 데이터는 산점도이며 예측값은 추세선이 된다.
R2를 계산하기 위해 아래와 같이 동일한 x값에서의 y값을 준비한다.
r2_score 함수는 Docs에서 확인할 수 있다.

from sklearn.metrics import r2_score
r2 = r2_score(df[5], trend_f(df['avg']))

최종적으로는 다음과 같은 결과를 얻을 수 있다.

df.plot(kind='scatter', x='avg', y=5)
fit_weight = np.polyfit(df['avg'], df[5], 1)
trend_f = np.poly1d(fit_weight)
r2 = r2_score(df[5], trend_f(df['avg']))
              
plt.plot(df['avg'], trend_f(df['avg']),"r-")
plt.title("y={:.6f}x+({:.6f}) [R2={:.6f}]".format(fit_weight[0], fit_weight[1], r2))
plt.show()

댓글 남기기