Coding Diary.

(데이터분석) matplotlib,seaborn에서 마커를 이용하여 다변량 변수 나타내기 본문

Coding/Data analysis

(데이터분석) matplotlib,seaborn에서 마커를 이용하여 다변량 변수 나타내기

life-of-nomad 2024. 5. 28. 13:05
728x90
반응형
지난 글에서 이변량 변수를 나타낼 때 자주 쓰이는 산점도에 대해 알아보았습니다. 이번 글에서는 세개 이상의 변수를 나타낼 때 쓰는 방법에 대해 알아보겠습니다.

 

 🔻(참고)산점도(scatterplot)🔻

 

(데이터분석) 산점도(scatterplots) 개념 및 matplotlib, seaborn으로 그리기

두 숫자 변수 사이에 존재하는 관계를 조사할 때 대표적으로 활용하는 차트는 산점도입니다.이번 글에서는 산점도와 matplotlib으로 그리는 방법에 대해 알아보겠습니다.  1. 산점도산점도에서

life-of-nomad.tistory.com

 

1. 세 개의 변수

  • 세 개의 변수를 차트에 나타내는 경우는 크게 네 가지가 존재합니다.
    • 세 개의 숫자 변수
    • 두 개의 숫자 변수와 한 개의 범주형 변수
    • 한 개의 숫자 변수와 두 개의 범주형 변수
    • 세 개의 범주형 변수
  • 숫자 변수 : 값에 의미가 있는 변수 (체중, 나이 등), 전화번호와 같은 값에는 그 자체적 의미가 없습니다.
  • 범주형 변수 : 특정한 유형 중 하나로 지정되는 변수 (생물의 종, 머리카락 색상)
  • 두 개 이상의 숫자 변수가 존재할 때는 일반적으로
    • 1)산점도를 사용해 두 개의 숫자 변수를 나타낸 다음,
    • 2)비위치적 부호를 각 점에 덧붙여서 숫자 또는 범주형의 세 번째 변수를 나타내는 방법을 많이 사용합니다. 
  • 주로 사용되는 비위치적 부호는 다음과 같습니다.
    • 마커의 색상
    • 마커의 모양
    • 마커의 크기
  • 이 중에서도 색상은 matplotlib과 seaborn에서 세 번째 변수에 가장 간편하게 적용할 수 있는 시각적 부호입니다. 
  • 색상은 정량적 데이터와 정성적 데이터를 모두 나타낼 수 있으며, 경우에 따라서 서로 다른 종류의 색상 팔레트가 사용됩니다.

 

2. 예시

1) 마커의 모양으로 나타내기

  • 먼저, 필요한 라이브러리와 연비 데이터세트를 불러오겠습니다.
import numpy as np
import pandas as pd

import matplotlib.pyplot as plt
import seaborn as sns
  • 차량을 자동과 수동으로 나누기 위해 trans_type으로 변속기의 종류 정보를 추출하겠습니다.
#load data
df = dp.read_csv('../data/fuel-econ.csv')

#create transmission type column
df['trans_type'] = df['trans'].apply(lambda x:x.split()[0])
  • 여기서, 데이터 양이 너무 많으므로 산점도가 과밀되지 않도록 200개의 차량 데이터를 무작위로 뽑겠습니다.
  • 그리고 해당 데이터에 수평 방향의 지터링을 적용해 각 점이 서로 겹치지 않도록 만들겠습니다.
#randomly sample data frame
np.random.seed(42)
sample = np.random.choice(df.shape[0], 200, replace = False) #replace=False: 중복없이 뽑기
df_subset = df.loc[sample]
  • regplot과 scatter 함수에는 매개변수 marker가 존재합니다. 
  • 이를 특정 문자열로 지정하면 그에 대응하는 마커를 사용할 수 있습니다.
  • 예를 들어, df_subset에서 자동 변속기인 차량을 선택한 다음 x축이 엔진 배기량이고 y축이 복합 연비를 나타내는 산점도를 그린다고 해봅시다. 
  • x값에는 약간의 지터링을 적용해 점이 겹치는 것을 막고 회귀선은 추가하지 않도록 하겠습니다.(fit_reg=False)
  • 마커는 삼각형을 사용하겠습니다.
sns.regplot(data=df_subset[df_subset['trans_type'] == 'Automatic'],
			x='displ', y='comb', x_jitter=0.04, fit_reg=False, marker='^');

  • 이제 자동과 수동인 차량을 모두 나타내봅시다. 
  • 그러기 위해서는 ttype이라는 리스트의 리스트를 만들어야 합니다.
  • 이 리스트의 리스트는 automatic 또는 manual로 나뉘는 범주와 각 범주를 나타낼 때 사용할 마커로 구성됩니다.
  • 그리고 이 리스트의 리스트를 순회합니다. 그 과정에서 각 리스트에 대한 산점도가 따로 작성됩니다.
  • 즉, 한 번에 한 가지의 변속기의 산점도를 그리는 것입니다.
ttype_markers = [['Automatic', 'o'], ['Manual', '^']]

for ttype, marker in ttype_markers:
	plot_data = df_subset.loc[df_subset['trans_type'] == ttype]
    	sns.regplot(data=plot_data, x='displ', y='comb', 
    			x_jitter=0.04, fit_reg=False, marker=marker);
        plt.xlabel('Displacement(1)')
        plt.ylabel('Combine Fuel Eff. (mpg)');
        plt.legend(['Automatic', 'Manual']); #범례 나타내기(리스트)

 

  • 산점도가 두 번에 나눠 작성되었기 때문에 seaborn이 각각을 고유의 색상으로 나타낼 수 있었습니다.

 

2) 마커의 크기로 나타내기

  • 이번에는 변속기 종류 대신 이산화탄소 배출량을 세번째 변수로 나타내보겠습니다.
  • CO2는 숫자변수 이므로 마커의 크기로 나타낼 수 있습니다. 
  • CO2값이 커질수록 더 큰 마커로 나타나게 됩니다.
  • matplotlib의 scatter(산점도) 함수에서는 매개변수 s로 마커의 크기를 설정할 수 있습니다.
  • regplot 안에서 scatter_kws라는 인수를 통해 인수 s를 딕셔너리 형태로 설정합니다. 
  • CO2의 값은 2로 나누어 반영하겠습니다. 
sns.regplot(data=df_subset, x='displ', y='comb', x_jitter=0.04,
        fit_reg=False, scatter_kws={'s': df_subset['co2']/2}, label='co2'); #label:범례
plt.xlabel('Displacement(1)')
plt.ylabel('Combine Fuel Eff. (mpg)');
plt.legend();

  • 결과를 보면 엔진 배기량이 늘어날수록 원도 커지는 경향을 보입니다. 즉, CO2 배출량도 늘어나는 것입니다.
  • 하지만, CO2는 숫자 데이터인데 이것만으로는 그 값을 가늠하기 어렵습니다.
  • 마커의 크기를 통해 배출량을 파악할 수 있게 하려면 범례를 통해 서로 다른 크기가 나타내는 값을 밝혀야 합니다.
  • 하지만 문제는, CO2라는 하나의 산점도만 존재하기 때문에 지금과 같이 범례에 하나의 점만 표시된다는 것입니다. 
  • 이를 해결하기 위해서 여러 개의 가짜 산점도를 순차적으로 작성해서 자체적인 범례를 만들겠습니다. 
sns.regplot(data=df_subset, x='displ', y='comb', x_jitter=0.04,
	fit_reg=False, scatter_kws={'s': df_subset['co2']/2});
plt.xlabel('Displacement(1)')
plt.ylabel('Combine Fuel Eff. (mpg)');

sizes = [200, 350, 500]
legend_obj = []
for s in sizes: #각 크기에 대해 점이 없는 산점도 작성/이미 작성된 산점도 위에 가짜 산점도 추가로 작성됨
	legend_obj.append(plt.scatter([], [], s=s/2, color='tab:blue'))

plt.legend(legend_obj, sizes, title = 'CO2 (g/mi)');

  • 이제 점의 크기가 나타내는 값을 파악할 수 있는 범례가 추가되었습니다.
  • 지난 글에서는 legend 함수에 차트의 레이블을 지정하는 하나의 인수만 추가했습니다.
  • 하지만 이번에는 legend 함수가 두세개의 인수를 갖게 됩니다.
  • plt.legend(범례 객체, 이름의 리스트, 범례의 이름(선택))

3)  마커의 색상으로 나타내기

  • 데이터를 시각화할 때는 주어진 데이터의 종류에 따라 그에 맞는 색상 팔레트를 선택하는 것이 좋습니다.
  • 색상 팔레트는 크게 세 가지 종류로 구성됩니다.
  • 1) 정성적 팔레트(Qualitative Palette) : 명목 데이터 나타낼 때 
sns.palplot(sns.color_palette(n_colors=9)

  • 2) 순차적 팔레트(Sequential Palette) : 숫자 데이터 나타낼 때
sns.palplot(sns.color_palette('viridis', 9))

  • 3) 발산 팔레트 (Diverging Palette) : 해당 변수의 중앙값이 존재할 때
sns.palplot(sns.color_palette('vlag', 9))

출처 ❘ Udacity

 

(1) 변속기 종류별로 색상 추가하기 

  • seaborn 차트에는 다양한 방식으로 색상을 추가할 수 있습니다.
  • 여기서는 Facetgrid를 사용해서 매개변수 hue를 지정해 색상을 추가하여 변속기 종류를 나타내보겠습니다.
  • 먼저, 연비와 엔진 배기량의 관계를 나타내는 산점도를 작성하겠습니다.
#hue: 서로 다른 변속기 종류
#hue_order: 차트에 반영할 순서
#여기서는 하나의 차트만 생성하기 때문에 aspect(가로와 세로의 비)를 1.5로 설정해서 가로가 세로보다 50%길어지게 설정
g = sns.FacetGrid(data=df_subset, hue='trans_type', 
		hue_order=['Automatic', 'Manual'], aspect=1.5)
g.map(sns.regplot, 'displ', 'comb', fit_reg=False);
g.add_legend()
plt.xlabel('Displacement(1)')
plt.ylabel('Combine Fuel Eff. (mpg)');

 

(2) 차급별 색상 추가하기

  • 그 다음, 색상으로 차 급을(VClass) 나타내보겠습니다.
  • VClass는 순서가 존재하는 변수이므로 정성적 팔레트는 어울리지 않습니다. 
  • 대신, 순차적 팔레트를 쓰는게 좋습니다. 이는 FacetGrid의 매개변수 palette로 지정할 수 있습니다.
  • 팔레트의 이름을 나타내는 문자열은 matplotlib과 동일합니다. (viridis_r)
g = sns.FacetGrid(data=df_subset, hue='VClass', aspect=1.5, palette='viridis_r')
g.map(sns.regplot, 'displ', 'comb', fit_reg=False);
g.add_legend()
plt.xlabel('Displacement(1)')
plt.ylabel('Combine Fuel Eff. (mpg)');

  • 이 팔레트는 명도의 차이 뿐만 아니라 적절한 범위의 색조를 사용해서 서로 다른 차급을 잘 구분해냅니다. 

(3) 이산화탄소 배출량에 따른 색상 추가하기

  • 만약, 색상을 통해 이산화탄소 배출량과 같은 숫자 변수를 나타내려면 매개변수 hue를 해당 변수로 지정할 수는 없습니다.
  • FaceGrid는 범주형 변수를 기준으로만 면 분할을 실행하기 때문입니다. 
  • 따라서, matplotlib의 기본적인 scatter 함수를 사용해서 차트를 작성해야 합니다. 
  • 이때 지터링은 사용할수 없으며 색상 매개변수의 상호작용 때문에 색상으로는 값을 분명하게 나타내기 어려워집니다.
  • scatter로 세 번째 숫자 변수를 추가할 때는 간단하게 매개변수 c를 추가하면 됩니다. (c는 color을 뜻함)
  • 또한 매개변수 cmap으로 색상 팔레트를 설정할 수도 있습니다.
  • 마지막으로, colorbar에는 레이블을 추가해서 색상이 나타내는 정보를 명확하게 설명해야 합니다. 
plt.scatter(data=df_subset, x='displ', y='comb', c='co2', cmap='viridis_r')
plt.colorbar(label='CO2 (g/mi)')
plt.xlabel('Displacement(1)')
plt.ylabel('Combine Fuel Eff. (mpg)');

728x90
반응형