파이썬 EDA를 하는 데 정말 중요한 주요 시각화 그래프에 대해 정리한다.
모든 그래프를 다루진 않으며, 많이 쓰이는 그래프를 중심으로만 정리하였다. 구체적으로는 데이터 종류(수치형, 범주형 데이터)에 따라, 변수 개수(1개, 2개 이상)에 따라 어떤 그래프를 그려야 할지를 정리하였다.
주피터 노트북 코드는 다음 깃허브에서 '1. [EDA guide] 주요 데이터 시각화' 파일을 공유해두었다 :)
이번 포스팅에서는 수치형 데이터(numerical data)를 시각화하는 방법을 다룬다.
참고로 시각화 라이브러리는 seaborn을 위주로 작성하였다.
✔Table of Contents
1. 데이터의 종류
먼저 데이터에는 크게 '수치형 데이터(numerical data)'와 '범주형 데이터(categorical data)'가 있다.
쉽게 말하자면 수치형 데이터는 사칙연산이 가능하며 범주형 데이터는 사칙연산이 불가능하다.
- 수치형 데이터 (numerical data) → 사칙연산 O
- 연속형 데이터 (continuous data) : 실수 형태 (e.g. 키, 몸무게)
- 이산형 데이터 (discrete data) : 정수 형태 (e.g. A반 학생 수)
- 범주형 데이터 (categorical data) → 사칙연산 X
- 순서형 데이터 (ordinal data) : 순위(순서)가 있는 데이터 (e.g. 학점, 설문조사 점수)
- 명목형 데이터 (nominal data) : 순위(순서)가 없는 데이터 (e.g. 성별, 우편번호)
이렇게 정리할 수 있으며, 우리가 대부분 만나는 데이터는 수치형 데이터와, 범주형 데이터 중 명목형 데이터이다.
보통 수치형 데이터는 숫자로 된 데이터, 범주형 데이터는 숫자가 아닌 문자로 된 데이터라고 생각하기 쉬운데,
그런 경우도 있지만 예를 들어 범주형 데이터에서 여성이 1, 남성이 0 으로 된 경우도 있기 때문에 사칙연산이 되는지, 숫자가 연속되어 있는지의 여부로 구분하는 것이 좋다.
2. 수치형 데이터 시각화
수치형 데이터는 사칙연산이 가능하며, 정수 또는 실수형태의 데이터로 구성된다.
수치형 데이터를 시각화할 때는 데이터가 어떻게 분포(distribution)되어 있는지를 확인하는 게 중요하다.
데이터는 유명한 데이터인 'tips'를 사용하였다. (굳이 데이터셋을 다운받지 않아도, 다음 코드를 치면 자동으로 다운된다!)
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
tips = sns.load_dataset('tips')
tips.head()
tips.describe()
보통 수치형 데이터는 describe 메서드로 확인했을 때 나온다. 문자형으로 되어 있으면 describe에서 값이 나오지 않기 때문!
하지만 앞에서도 얘기했듯, 범주형 데이터인데 숫자로 된 경우가 있어 주의하자.
tips 데이터셋에서 수치형 데이터(그 중에서도 연속형 데이터)인 total_bill, tip에 대해 시각화를 해보자.
2-1. 수치형 변수 1개 시각화
- 히스토그램: plt.hist()
- 분포도(히스토그램+커널밀도함수): sns.distplot()
- 박스플롯: sns.boxplot()
1) 히스토그램(Histogram)
수치형 데이터를 구간별로 나눠 그린 빈도수 그래프이다. matplotlib을 사용한다.
형태는 data[col].hist() 를 사용하거나, 또는 plt.hist(data[col])의 형태이다.
plt.hist(tips['total_bill'])
## 다음의 코드도 동일한 그래프
#tips['total_bill'].hist()
#tips['total_bill'].plot.hist()
plt.show()
bins 옵션을 활용해 구간의 수를 늘릴 수 있다. 20개로 늘려보자.
# bins 고정
plt.hist(tips['total_bill'], bins = 20)
plt.show()
y축은 현재 빈도수(frequency)로 되어 있는데, 이를 비율로 바꾸려면 density = True 옵션을 준다.
# y축 비율로 바꿈
plt.hist(tips['total_bill'], bins = 20, density = True)
plt.show()
2) 분포도(distplot)
seaborn(이하 'sns') 에서 제공하는 함수로, 히스토그램과 커널밀도함수 그래프를 함께 그려주는 그래프이다.
보통 분포를 확인할 때 일반적으로 distplot을 사용한다.
형태는 sns.distplot(data[x], kde = True, hist = True)
sns.distplot(tips['total_bill'])
plt.show()
디폴트 옵션을 조금 바꿔보자.
kde = False로 하면 히스토그램이 된다.
sns.distplot(tips['total_bill'], kde = False, hist = True) #히스토그램
plt.show()
반대로 hist = False로 바꾸면 커널밀도함수 그래프가 된다.
sns.distplot(tips['total_bill'], kde = True, hist = False) #커널밀도그래프
plt.show()
3) 박스플롯(Boxplot)
위의 2개 그래프가 전체 분포 현황을 직관적으로 보여준다면,
boxplot은 박스와 수염 모양으로 여러 가지 정보를 알려준다. (최솟값, 최댓값, Q1, Q2(중위수), Q3 값)
형태는 sns.boxplot(x or y, data)
sns.boxplot(tips['total_bill'])
plt.show()
또는 이렇게 써도 된다.
# 디폴트
sns.boxplot(x = 'total_bill', data = tips)
plt.show()
여기서 boxplot을 세로 모양으로 세우고 싶다면, x 옵션을 y로 바꾸면 된다.
# boxplot 세우기
sns.boxplot(y = 'total_bill', data = tips)
plt.show()
2-2. 수치형 변수 2개 이상 시각화(변수 간 관계 확인)
- 히트맵: sns.heatmap()
- 라인플롯: sns.lineplot()
- 산점도: sns.scatterplot()
- 회귀선 + 산점도: sns.regplot()
1) 히트맵(heatmap)
보통 히트맵은 수치형 변수들 간의 상관관계를 나타낼 때 자주 사용한다.
tips 데이터셋의 상관계수를 구해보자. corr() 함수를 사용한다.
tips.corr()
숫자값이 있는 변수에 대해서만 상관계수가 구해진다.
참고로 상관계수란 -1에서 1 사이의 값을 가지며, 절댓값이 1에 가까울수록 2개 변수 간 상관성이 높다고 볼 수 있다.
(즉, 상관계수가 1에 가까우면 두 변수는 정비례 / 상관계수가 -1에 가까우면 두 변수는 반비례한다는 뜻!)
이렇게 만들어진 데이터프레임을 그대로 sns.heatmap 안에 넣으면 상관관계 그래프가 그려진다.
# 위의 테이블 형태를 그대로 sns.heatmap 안에 넣으면 끝
tip_cor = tips.corr()
sns.heatmap(tip_cor)
상관계수가 높을수록 두 변수 간의 상관성이 높다.
오른쪽의 색상 막대(colorbar)를 보면, 색이 옅은 색에 가까울수록 상관성이 높다고 되어 있다.
그러니 그래프를 보면 tip과 total_bill 간의 양의 상관성이 높음을 알 수 있다!
또한, 이런 상관계수 테이블뿐만 아니라 피봇 테이블(pivot table) 형태로 만들어서 히트맵 안에 넣어 관계를 확인할 수 있다.
시간(time)과 식사 인원 수(size)에 따라 팁(tip)이 어떻게 변동하는지 궁금하다고 할 때, 데이터를 피봇테이블로 변형해보자.
(index와 colum 값을 범주형 데이터로 넣고, 이 값에 따라 수치형 데이터가 어떻게 변동하는지(values 값) 알아볼 때 유용하다.)
tip_pivot = pd.pivot_table(index = 'time', columns = 'size', values = 'tip', data = tips)
tip_pivot
time과 size에 따라 tip의 값이 구해졌다.
당연히 상관계수를 나타낸 것은 아니고, time과 size에 따른 tip의 평균값이다.
'tip_pivot' 테이블을 그대로 히트맵에 넣어보자.
sns.heatmap(tip_pivot)
색이 옅을수록 tip이 커지는데, 주로 size가 커질수록, Lunch 일수록 tip이 커지는 경향이 있다.
하지만 size가 2-3명인 경우는 Dinner일 때 tip을 더 많이 주었다.
2) 라인플롯(lineplot)
라인플롯은 두 수치형 데이터 사이의 관계를 선으로 나타낸다.
주로 x축에는 이산형(discrete) 데이터, y축에는 연속형(continuous) 데이터를 쓸 때 사용한다.
그 이유는 x값에 따른 y값의 평균값을 선으로 이어주기 때문이다.
형태는 sns.lineplot(x, y, hue(범주형), data)
# 두 수치형 데이터 size, tip 간 관계를 시각화
sns.lineplot(x = 'size', y = 'tip', data = tips)
위와 같이, size라는 이산형 데이터를 x축에, tip이라는 연속형 데이터를 y축에 사용하였다.
그럼 size에 따른 평균 tip 값이 선으로 이어진다.
중심선은 평균, 선 옆의 옅은 색은 95% 신뢰구간(CI)을 의미한다.
참고로 seaborn에는 'hue'라고 하는 아주 유용한 기능이 있다. 여기에 범주형 데이터를 넣어, 위 그래프를 hue 값에 따라 나눠서 살펴볼 수 있다!
예를 들어 size에 따른 평균 tip 값이 궁금한데, smoker(흡연) 여부에 따라 달라지는지 궁금하다면..
# 참고로 hue에 범주형 데이터를 넣어서 선을 다양화할 수 있다.
# size와 tip의 라인플롯 - smoker 여부에 따라 달라지는지 체크
sns.lineplot(x= 'size', y = 'tip', hue = 'smoker', data = tips)
그런데 꼭 x축에 이산형, y축에 연속형 데이터만 넣어야 하는 걸까?
x축에 연속형, y축에도 연속형 데이터를 쓸 수도 있다! 그런데 total_bill과 tip 간의 라인플롯을 그려보면
# 만일 x, y 둘 다 연속형을 쓰면,, 그림이 좀 이상해짐
sns.lineplot(x = 'total_bill', y = 'tip', data = tips)
이렇게 좀 보기 싫은(?) 그림이 나온다.
그래서 x, y 모두 연속형 데이터를 쓴다면 바로 밑에서 이어지는 산점도(scatterplot)을 쓰는 것을 추천한다.
3) 산점도(scatterplot)
산점도는 두 수치형 데이터 간의 관계를 점으로 나타낸다.
주로 x, y축에 모두 연속형 데이터를 넣을 때 자주 사용한다.
형태는 sns.scatterplot(x, y, hue(범주형), data)
# 위에서 이상해보였던 total_bill과 tip 간 그래프를 산점도로 다시 그려보자
sns.scatterplot(x = 'total_bill', y = 'tip', data = tips)
이번엔 그래프가 알아보기 쉽게 잘 그려졌다!
마찬가지로 hue에 범주형 변수를 넣어 구분지을 수 있다. 성별에 따라 total_bill과 tip 간 산점도를 그려보자.
# 마찬가지로 hue에 범주형 변수를 넣어 시각화 가능
# total_bill과 tip 간 그래프를 성별에 따라 나눠 그리면
sns.scatterplot(x = 'total_bill', y = 'tip', data = tips, hue = 'sex')
산점도를 그릴 때도 x축과 y축 모두 연속형 변수만을 넣어야 하는 것은 아니다.
앞서 라인플롯에서 봤던 x축: size, y축: tip을 이번엔 산점도로 그려보자.
# 물론 산점도에도 이산형 변수에 따라 연속형 변수를 그려도 됨
sns.scatterplot(x = 'size', y = 'tip', data = tips)
이렇게 그래프가 그려지긴 하지만, lineplot이 좀 더 직관적으로 눈에 잘 들어오니 lineplot을 쓰는 게 더 좋아보인다.
4) regplot: 회귀선 + 산점도
회귀선과 산점도를 동시에 그려주는 유용한 함수이다.
마찬가지로 x와 y 모두 연속형 데이터일 때 자주 사용한다.
형태는 sns.regplot(x, y, data, marker, ci, data)
위에서 그린 total_bill과 tip 간의 산점도를 이번엔 regplot으로 그려보자.
# total_bill & tip 간 관계
sns.regplot(x= 'total_bill', y = 'tip', data = tips)
회귀선까지 함께 그려주니, 좀 더 두 변수 간의 양의 상관관계가 돋보인다!
이번엔 여러 꾸미기 옵션을 줘봤다.
# 꾸미기 옵션
# 99% 신뢰구간으로 늘리면
sns.regplot(x= 'total_bill', y = 'tip', data = tips, ci = 99)
위처럼 ci 값을 설정하면 신뢰구간 값이 늘어난다.
디폴트는 95% 신뢰구간이다.
# marker 모양 바꾸기
sns.regplot(x= 'total_bill', y = 'tip', data = tips, marker= '+')
marker 옵션으로 점의 모양도 바꿀 수 있다.
x, y 모두 연속형 변수일 때 사용하는 게 좋다고는 했지만, x가 이산형 변수일 때도 역시 그릴 수 있다.
sns.regplot(x = 'size', y = 'tip', data = tips)
이렇게 x가 이산형 변수일 때, 여러 옵션을 사용할 수 있다.
대표적으로 2개의 옵션이 있다.
- jitter: x_jitter, y_jitter를 사용할 수 있으며 x또는 y 변수에 약간의 노이즈를 첨가한 그래프를 그린다.
- x_estimator: x가 이산형일 때 유용하게 쓰이며, x값에 따른 y값의 지표를 설정한다.
sns.regplot(x = 'size', y = 'tip', data = tips, x_jitter = .1)
이처럼 x_jitter를 이용해 노이즈가 좀 더 생긴 그래프가 그려졌다.
import numpy as np
sns.regplot(x = 'size', y = 'tip', data = tips, x_estimator = np.mean)
x_estimator를 평균값으로 설정하였다.
그럼 size에 따른 tip의 평균값 그래프가 도출되며, lineplot과 비슷한 그래프이다.
이렇게 수치형 변수(이산형, 연속형)일 때 그릴 수 있는 그래프에 대해 알아보았다.
다음 포스팅에선 범주형 변수일 때 그리는 그래프에 대해 알아보자!
'Skillset > Python, Git' 카테고리의 다른 글
[시각화] 파이썬 EDA에 꼭 필요한 시각화 그래프 (3) plt.subplots 사용하기 (0) | 2022.06.16 |
---|---|
[시각화] 파이썬 EDA에 꼭 필요한 시각화 그래프 (2) 범주형 데이터 (0) | 2022.06.16 |
python dlib 설치하기 - anaconda dlib install error (0) | 2022.04.23 |
python cv2 AttributeError: 'Nonetype' object has no attribute 'shape' 해결법 (2) | 2022.04.22 |
python pip upgrade error - pip 업그레이드 해결하는 방법 (6) | 2022.04.22 |