그래프와 시각화 3편

참고: 웨스 맥키니의 <파이썬 라이브러리를 활용한 데이터 분석>의 9장 2절에 사용된 소스코드를 활용한다.

pandas로 그래프 그리기

판다스의 시리즈(Series)와 데이터프레임(Dataframe) 객체 모두 plot() 메서드를 지원한다. 실제로는 matplotlib.pyplot.plot()을 이용하기에 xticks, xlim 등 옵션 사용방식 또한 거의 동일하다. 자세한 옵션과 사용법은 공식문서를 참고한다.

시리즈와 선그래프

시리즈는 하나의 선그래프를 그릴 수 있으며, 항목ㅣ y축 좌표로, 인덱스가 x축 좌표로 사용된다.

데이터프레임과 선그래프

데이터프레임은 특성 수만큼의 선그래프를 그릴 수 있다. y축 좌표는 특성별 항목이며, x축 좌표는 기본적으로 인덱스가 사용된다. 또한 특성 이름이 범례로 지정된다.

subplots=True 키워드 인자를 사용하면 각각의 그래프를 1차원 어레이 모양의 독립된 서브플롯에서 그린다.

시리즈와 막대그래프

아래 코드는 시리즈를 이용한 수직/수평 막대그래프를 그리는 기본적인 방법을 보여준다. 수평 막대그래프의 x축/y축 눈금은 수직 막대그래프의 y축/x축 눈금에 해당한다.

참고: 서브플롯을 지정하려면 ax=서브플롯 옵션을 지정하면 되며, 이는 시리즈와 데이터프레임의 모든 그래프 함수에 사용된다. 아래 데이터는 (2,1) 모양의 Figure 객체에 포함된 두 개의 서브플롯에 각각 수직/수평 막대그래프를 삽입한다.

plot() 메서드의 kind=barkind=barh 옵션

kind=bar/kind=barh 옵션이 각각 수직/수평 막대그래프를 그리는 함수와 동일하다.

데이터프레임과 막대그래프

아래 코드는 데이터프레임을 이용한 수직/수평 막대그래프를 그리는 기본적인 방법을 보여준다. 수평 막대그래프의 x축/y축 눈금은 수직 막대그래프의 y축/x축 눈금에 해당한다.

누적막대그래프

stacked=True 옵션을 사용하면 각 행의 값들이 하나의 막대에 누적되어 출력된다.

plot() 메서드의 kind=barkind=barh 옵션

kind=bar/kind=barh 옵션이 각각 수직/수평 막대그래프를 그리는 함수와 동일하다.

예제: 서비스 팁(tip) 데이터

서비스 팁 데이터는 요일별 파티 수, 총 수입, 시간대, 팁 수입 등에 대한 정보를 담고 있다.

참고: 서비스 팁 데이터를 아래처럼 불러올 수도 있다.

import seaborn as sns
tips = sns.load_dataset('tips').drop('sex', axis=1)

열별 특성은 다음과 같다.

범주형 데이터에 사용된 값들은 다음과 같다.

'size' 특성은 해당 파티 규모, 즉 파티 참여인원 수를 가리키며 최소 1명 최대 6명이 참여했다.

교차 테이블

요일과 파티 규모 사이의 관계를 파악하기 위해 교차표(cross table)를 이용한다. pandas.crosstab() 함수는 지정된 두 특성 사이의 도수분포도를 표로 생성한다.

빈도수가 낮은 1인과 6인 파티는 제외하자.

행별 정규화(Normalization)

행별로 항목의 합이 1이 되도록 값을 정규화한다. 이 과정을 통해 요일별 파티 규모의 비율을 파악할 수 있다.

요일별 파티 규모를 막대그래프로 그리면 다음과 같으며, 주말일 수록 파티 규모가 커짐을 쉽게 확인할 수 있다.

seanborn으로 그래프 그리기

seaborn 라이브러리는 matplotlib을 바탕으로 멋진 통계 관련 그래프를 그리는 API(도구)를 제공한다. 활용법 설명을 위해 서비스 팁(tip) 데이터를 계속 활용한다.

요일별로 총 순수수입에서 서비스 팁이 차지하는 비율을 특성으로 추가하자.

seaborn.barplot() 함수

요일별 서비스 팁의 비율의 평균값(mean)은 다음과 같다. 막대 끝에 위치한 검정 직선 기본적으로 신뢰도 95%의 신뢰구간을 표시하는 오차 막대(error bar)이다.

참고: 축에 사용될 값들은 열 특성이름을 이용하여 지정한다.

ci 옵션을 조절하면 신뢰구간을 표준편차로 바꾸거나 아무 것도 표시하지 않도록 할 수 있다.

참고: 목요일 저녁 막대에 신뢰구간이 표시되지 않는 이유는 단 한 번의 파티만 있었기 때문이다.

seaborn 기본 설정

seaborn.set_theme() 함수를 이용하여 다양한 설정을 지정할 수 있으며 사용 방식은 다음과 같다.

seaborn.set_theme(context='notebook', 
                  style='darkgrid', 
                  palette='deep', 
                  font='sans-serif', 
                  font_scale=1, 
                  color_codes=True, 
                  rc=None)

지정된 설정은 모든 그래프에 영향을 준다.

히스토그램과 밀도그래프

아래 pandas의 plot() 함수를 이용하여 히스토그램을 그리는 것을 보여준다. 사용되는 데이트는 요일별 팁의 비율이며 최고 2.5% 정도에 다다른다.

pandas.plot.density() 함수는 히스토그램에 대한 추정 연속확률밀도 함수의 그래프를 그린다.

seaborn 라이브러리를 이용하여 히스토그램과 밀도그래프를 함께 그릴 수도 있다. 이를 위해 seaborn.histplot() 또는 seaborn.displot() 함수를 kde=True (커널 밀도 추정) 옵션과 함께 사용한다.

주의사항: 책에서 사용한 아래 함수는 더 이상 지원되지 않는다.

seaborn.distplot(values, bins=100, color='k')

seaborn.histplot() 함수

seaborn.displot() 함수

seaborn.displot() 사용할 경우 사이즈와 가로세로의 기본 비율이 다르다.

하지만 heightaspect 옵션을 이용하면 적절한 크기와 비율로 맞출 수 있다.

예제: 서비스 팁 비율의 히스토그램과 밀도 그래프

산점도

산점도는 두 변수간의 관계를 좌표상의 점으로 표시하여 나타내는 그래프다. 산점도의 활용을 살펴보기 위해 1959년부터 2009년까지 미국의 거시경제지표를 담고 있는 데이터를 사용하며, statsmodels 모듈에서 불러온다.

포함된 14개의 경제지표는 다음과 같다.

지표 설명
year 1959년 1분기 - 2009년 3분기
quarter 1 - 4분기
realgdp 실질 국내총생산 (단위: 억 달러)
realcons 실질 총민간 소비지출 (단위: 억 달러)
realinv 실질 총민간 국내투자 (단위: 억 달러)
realgovt 실질 연방 정부 소비지출 및 국내투자 (단위: 억 달러)
realdpi 실질 가처분 소득 (단위: 억 달러)
cpi 소비자 물가지수
m1 M1 통화지표
tbilrate 3개월 만기 국채 수익률
unemp 실업률
pop 인구
infl 물가상승률
realint 실질 이자율

이중에 네 개의 지표만 이용해서 산점도를 설명한다.

시간의 흐름에 따른 변화량을 살펴보려 한다. 사용된 데이터의 척도(scale)을 맞추기 위해 로그값을 취한 후 분기별 변화량을 측정한다.

0번 행은 무조건 결측치가 포함되기에 삭제된다.

산점도와 선형회귀 곡선

seaborn.regplot() 함수는 산점도와 두 데이터 사이의 선형 관계를 보여주는 선형회귀 곡선을 동시에 그린다.

참고: 책 378쪽에서 사용하는 아래 방식은 더 이상 지원되지 않는다.

seaborn.regplot('m1', 'unemp', data=trans_data)

대신 아래 방식을 사용해야 한다.

seaborn.regplot(x='m1', y='unemp', data=trans_data)

사실 m1 데이터와 unemp 데이터 사이의 선형관계가 많이 있어보이지는 않는다. 실제로 두 특성 사이의 피어슨 상관계수는 0.15 정도로 매우 작다.

seaborn.heatmap() 함수를 이용하여 선형관계를 색으로 표현할 수 있다.

참고: 선형회귀 직선을 보이지 않으려면 fit_reg=False 옵션을 사용한다.

seaborn.regplot() 함수의 보다 다양한 기능은 공식문서를 참고한다.

산점도 행렬

상관계수와 히트맵의 경우처럼 가능한 모든 산점도를 한꺼번에 그릴 수 있다. 예를 들어 4개의 열 특성이 주어지면 4x4 모양의 격자를 산점도로 채운 그림이 그려진다. 대각선 상에는 해당 데이터의 도수분포도를 보여주는 히스토그램이 기본으로 입력된다.

diag_kind=kde 옵션을 사용하면 대각선 상에 히스토그램 대신 밀도그래프가 삽입된다.

패싯 그리드(Facet Grids)과 범주형 데이터

패싯그리드 클래스(seaborn.FacetGrid)는 여러 개의 pyplot.subplots() 함수와 비슷하게 작동한다. 다만, 지정된 옵션에 따라 격자 분할을 적절하게 지정한다.

참고: 책 380쪽에서 사용하는 seaborn.factorplot() 함수 이름이 seaborn.catplot() 으로 변경되었다.

아래 코드는 요일별 팁 비율을 막대그래프로 보여준다. 단, 1% 미만의 팁 비율만 다룬다. 또한 흡연 여부에 따라 두 개의 막대그래프를 열별로 그린다.

열뿐만 아니라 행별로 구분된 그래프를 그리려면 row 옵션 인자를 활용한다. 예를 들어, 앞서 hue='time' 옵션을 아래와 같이 바꾸면 두 개의 행에 걸쳐 서로 다른 시간대별 막대그래프를 그리며 결국 2x2 모양의 격자에 총 네 개의 막대그래프가 그려진다.

물론 아래와 같이 col 옵션을 지정하지 않으면 행별로 하나의 막대그래프만 그릴 수도 있다.

kind 옵션에 따라 다양한 그래프를 그린다. 보다 자세한 내용은 seaborn.catplot 공식 문서를 참고한다.

아래 코드는 데이터의 중간값, 사분위수, 이상치 등을 보여주는 상자그림(box plot)를 그린다.

기타 시각화 도구 안내

matplotlib과 seaborn 등은 출판용도의 정적 그래프를 생성한다. 반면에 웹에서 동적 대화형으로 작동하는 그래프를 파이썬으로 그리려면 Bokeh 또는 Plotly 등을 이용할 수 있다.