데이터 분석 과정 학습 및 시각화 실습(3)-2

2024. 1. 10. 18:29TIL

seaborn 소개

 Seaborn은 Python에서 통계 그래픽을 만들기 위한 라이브러리이다. matplotlib을 기반으로 하며 pandas 데이터 구조와 밀접하게 통합된다. Pandas DataFrame과 직관적으로 연계되기 때문에 쉽고 빠르게 데이터 시각화가 가능하다. Seaborn에서 사용할 수 있는 플롯들은 크게 다음 3가지 종류의 플롯군으로 나뉜다.

  • Relplot: 2개 이상의 변수간의 관계를 효과적으로 나타내는 플롯
    • scatterplot
    • lineplot
  • Displot: 1개 이상의 변수 값의 분포를 효과적으로 나타내는 플롯
    • hisplot
    • kdeplot
    • ecdfplot
    • rugplot
  • Catplot: 범주형 데이터의 분포를 효과적으로 나타내는 플롯
    • stripplot
    • swarmplot
    • boxplot
    • violinplot
    • pointplot
    • barplot
seaborn plot 종류 - Relplot (Relational)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

tips = sns.load_dataset("tips")
# scatter plot
# 두개의 연속형 변수 total_bill과 tip간의 관계를 scatter plot으로 표현
sns.relplot(data=tips, x="total_bill", y="tip")
sns.scatterplot(data=tips, x="total_bill", y="tip")
# 크게 hue, size, style을 통해서 데이터포인트가 가지는 categorical 변수값을 표현할 수 있음
sns.relplot(
    data=tips,
    x="total_bill", y="tip", hue="smoker", style="time",size="size"
)
# hue가 가지는 값이 연속형 변수인 경우 색이 pallete형태로 표현
sns.relplot(
    data=tips, x="total_bill", y="tip", hue="size",
)
# size를 사용하는 경우 sizes=(a,b) 옵션을 통해 점들의 크기를 조정
sns.relplot(
    data=tips, x="total_bill", y="tip", size="size", sizes=(15,200)
)

# Lineplots
dowjones = sns.load_dataset("dowjones")
# 시간과 같이 지속성을 가진 변수과 다른 변수의 관계를 나타낼 때는 lineplot이 효과적
sns.relplot(data=dowjones, x="Date", y="Price", kind="line")
sns.lineplot(data=dowjones, x="Date", y="Price")

fmri = sns.load_dataset("fmri")
# x축 값 하나에 따른 y값이 하나가 아닌 다양한 값을 갖고 있을 수도 있다
# 기본적으로, lineplot은 여러 값들을 모아서 평균을 선으로, 95% 신뢰구간을 색으로 표현
# sns.relplot(data=fmri, x="timepoint", y="signal", kind="line")
sns.lineplot(data=fmri, x="timepoint", y="signal")
# CI를 표시하지 않으려면 errorbar=None으로
# 표준편차의 범위로 표시하고싶으면 errorbar='sd'로 옵션
sns.relplot(
    data=fmri, kind="line",
    x="timepoint", y="signal", errorbar=None,
)
sns.relplot(
    data=fmri, kind="line",
    x="timepoint", y="signal", errorbar='sd',
)
# hue나 style을 이용해서 여러 카테고리의 선과 밴드로 나눠서 표현
sns.relplot(x="timepoint", y="signal", hue="event", kind="line", data=fmri)
sns.relplot(x="timepoint", y="signal", hue="region", style="event",
            kind="line", data=fmri)
sns.relplot(x="timepoint", y="signal", hue="region", style="event",
            dashes=False, markers=True, kind="line", data=fmri)

# hue를 통해서 연속형 변수 또한 구분하여 lineplot 을 그릴 수 있다
dots = sns.load_dataset("dots").query("align == 'dots'")
sns.relplot(
    data=dots, kind="line",
    x="time", y="firing_rate",
    hue="coherence", style="choice",
)
# palette를 이용하여 선의 색 차이를 조정
palette = sns.cubehelix_palette(light=.9, n_colors=6)
sns.relplot(x="time", y="firing_rate",
            hue="coherence", style="choice",
            palette=palette,
            kind="line", data=dots)
# size를 이용해서 선의 굵기를 조절
palette = sns.cubehelix_palette(light=.9, n_colors=6)
sns.relplot(x="time", y="firing_rate",
           hue="coherence", size="choice",
           palette=palette,
           kind="line", data=dots)

# 변수가 많아질수록 한 플롯 안에서 표현하다 보면 가시성이 떨어지고 
# 효과적인 분석이 어려울 수 있다
# facet, 즉 여러 플롯으로 나눠 분석을 하는 것이 효과적일 수 있다
sns.relplot(x="total_bill", y="tip", hue="smoker",
            col="time", data=tips)
# col이나 row를 이용해 플롯들을 나누고 height을 통해서 플롯의 크기를 조절           
sns.relplot(x="timepoint", y="signal", hue="subject",
            col="region", row="event", height=3.5,
            kind="line", estimator=None, data=fmri)

 

seaborn plot 종류 - Displot (Distributions)
# 변수 하나 혹은 두 개의 분포를 나타낼 때 distplot에 포함된 여러 플롯들을 사용하면
# 해당 변수 값이 가지는 분포 및 범위를 효과적으로 확인할 수 있다
# 기본적으로 displot을 사용하면 히스토그램을 그려준다
# histogram
penguins = sns.load_dataset("penguins")
sns.histplot(penguins, x="flipper_length_mm")
sns.displot(penguins, x="flipper_length_mm")
# histogram의 막대 너비는 binwidth 혹은 bins를 사용해 조절
sns.displot(penguins, x="flipper_length_mm", bins=20)

# 변수가 이산형 변수인 경우, discrete=True 옵션을 통해 x축 값 중앙에 막대가 위치
sns.displot(tips, x="size", discrete=True)
# shrink 옵션을 통해 막대 간 공간 조절
sns.displot(tips, x="size", discrete=True, shrink=.7)

# displot의 경우 hue 옵션을 통해 추가 변수를 조건으로 한 분포를 시각화 
sns.displot(penguins, x="flipper_length_mm", hue="species")
# 막대 간 겹쳐지는 부분의 경우 element=step 옵션이나 ultiple={stack, dodge} 옵션을 사용 가능
sns.displot(penguins, x="flipper_length_mm", hue="species", element="step")
sns.displot(penguins, x="flipper_length_mm", hue="species", multiple="stack")
sns.displot(tips, x="size", discrete=True, shrink=.7, hue='sex', multiple='dodge')

# distplot 또한 col이나 row를 이용해 변수에 따른 여러 플롯으로 나눠 그릴 수 있다
sns.displot(penguins, x="flipper_length_mm", col="sex")
# stats='probability' 옵션을 통해 모든 막대의 높이의 합이 1이 되게 만들 수 있으며, 
# 이를 빈도의 비율값으로 해석할 수 있다
sns.displot(penguins, x="flipper_length_mm", hue="species", stat="probability")
# kde plot을 이용해 histogram과 다른 부드러운 곡선으로 이어진 분포 시각화
sns.kdeplot(penguins, x="flipper_length_mm")
# bw_adjust를 이용해 곡선을 세밀하게 혹은 더 부드럽게 표현
sns.displot(penguins, x="flipper_length_mm", kind="kde", bw_adjust=.25)

# kde plot 또한 hue를 이용해서 변수간 분포를 더 세밀하게 시각화
sns.displot(penguins, x="flipper_length_mm", hue="species", kind="kde")
# fill=True 옵션을 이용해 곡선 아래 색칠된 형태로 표현
sns.displot(penguins, x="flipper_length_mm", hue="species", kind="kde", fill=True)

# hue 옵션을 사용하는 대신, y에 2번째 변수를 넣어 여러 변수의 분포를 표현하는 시각화
# 기본적으로 displot은 heatmap을 그려준다
sns.displot(penguins, x="bill_length_mm", y="bill_depth_mm")
# kde plot에서 y 변수를 추가해주면 등고선 플롯을 그려준다
sns.displot(penguins, x="bill_length_mm", y="bill_depth_mm", kind="kde")

# heatmap과 contour plot 또한 hue 옵션을 추가해서 hue 변수에 따라 여러 분포를 구별해서 볼 수 있다
sns.displot(penguins, x="bill_length_mm", y="bill_depth_mm", hue="species")
sns.displot(penguins, x="bill_length_mm", y="bill_depth_mm", hue="species", kind="kde")

# heatmap의 경우 (x축,y축)의 binwidth를 조절하여 각 칸의 크기를 조절
# cbar=True 로 설정시 색깔에 따라 갖는 빈도 값을 확인할 수 있다
sns.displot(penguins, x="bill_length_mm", y="bill_depth_mm", binwidth=(2, .5), cbar=True)
# 등고선 플롯의 경우 thresh와 levels를 이용해 선의 간격을 조절
sns.displot(penguins, x="bill_length_mm", y="bill_depth_mm", kind="kde", thresh=.2, levels=4)
sns.displot(penguins, x="bill_length_mm", y="bill_depth_mm", kind="kde", 
	levels=[.01, .05, .1, .8])

# joint plot의 경우 2개의 변수 간 분포와 각 변수의 분포를 동시에 보여준다
sns.jointplot(data=penguins, x="bill_length_mm", y="bill_depth_mm")
# kind=’kde’ 인 경우 contour plot과 kde plot을 그려줍니다
sns.jointplot(
    data=penguins,
    x="bill_length_mm", y="bill_depth_mm", hue="species",
    kind="kde"
)

# Pair plot을 이용해 각 변수들간의 pairwise 관계를 시각화할 수 있다
# 특히, 고려해야할 변수들이 많은데 변수간 상관관계 파악이 필요한 경우 유용
sns.pairplot(penguins)

 

seaborn plot 종류 - Catplot (Categorical)
tips = sns.load_dataset("tips")
# catplot의 기본 플롯은 strip plot이며, 한쪽 변수가 categorical 데이터인 산점도
'''
catplot에서 사용 가능한 플롯들은 크게 다음 3가지로 나뉜다:
- 범주형 산점도: strip plot, swarm plot
- 범주형 분포도: box plot, violin plot
- 범주형 추정도표: bar plot, point plot
'''
# 한 범주에 속하는 모든 점이 범주형 변수에 해당하는 축을 따라 동일한 위치에 있게 된다
sns.catplot(data=tips, x="day", y="total_bill")
# jitter 옵션을 통해서 좌우로 퍼진 정도를 조절하거나 비활성화
sns.catplot(data=tips, x="day", y="total_bill", jitter=.3)
sns.catplot(data=tips, x="day", y="total_bill", jitter=False)

# swarm plot을 활용하면 점들의 중첩을 방지하는 알고리즘을 사용하여 시각화
# 상대적으로 데이터 수가 적은 경우에만 잘 작동하지만 관측치 분포를 더 잘 표현할 수 있다
# sns.swarmplot(data=tips, x="day", y="total_bill")
sns.catplot(data=tips, x="day", y="total_bill", kind="swarm")
# 관계형 도표와 마찬가지로 hue를 사용하여 범주형 도표에 다른 차원을 추가할 수 있다
# size또는 style는 지원되지 않는다
sns.catplot(data=tips, x="day", y="total_bill", hue="sex", kind="swarm")

# 데이터에 pandas Categorical 데이터 유형이 있는 경우 범주의 기본 순서를 여기에서 설정할 수 있다
tips['day'].dtype
# 데이터 유형이 Categorical이 아닌 경우에도 적용 가능하지만 
# Categorical 데이터로 취급되어 문제가 발생하는 경우가 있다
sns.catplot(data=tips.loc[tips['size']!=3], x="size", y="total_bill")
# 이 때, native_scale을 사용하면 x축 데이터의 분포를 보존할 수 있다
sns.catplot(data=tips.loc[tips['size']!=3], x="size", y="total_bill", native_scale=True)

# order 옵션을 사용해서 Categorical 변수의 순서를 바꿔줄 수도 있다
sns.catplot(data=tips, x="smoker", y="tip", order=["No", "Yes"])
tips['smoker'].dtypes # categories=['Yes', 'No']
# x와 y에 들어가는 변수 이름에 따라 축을 가로로 변경 가능
sns.catplot(data=tips, x="total_bill", y="day", hue="time", kind="swarm")

# boxplot
# 데이터 세트의 크기가 커짐에 따라 
# 범주형 산점도는 각 범주 내의 값 분포에 대해 제공할 수 있는 정보가 제한
# 이 때 boxplot을 사용할 수 있다
# sns.boxplot(data=tips, x="day", y="total_bill")
sns.catplot(data=tips, x="day", y="total_bill", kind="box")
# hue를 추가 가능하며 각 수준에 대한 상자는 더 좁아지고 범주형 축을 따라 이동된다.
sns.catplot(data=tips, x="day", y="total_bill", hue="smoker", kind="box")

# boxen plot을 이용하면 분위수를 좀 더 자세하게 표시할 수 있습니다
diamonds = sns.load_dataset("diamonds")
sns.boxenplot(data=diamonds.sort_values("color"), x="color", y="price")
sns.catplot(
    data=diamonds.sort_values("color"),
    x="color", y="price", kind="boxen",
    )
    
# violin plot
# violin plot은 box plot과 kde 곡선을 결합한 형태
# Boxplot에서 쓰인 IQR과 whisker 또한 표현된다
sns.violinplot(
    data=tips, x="total_bill", y="day", hue="sex",
)
sns.catplot(
    data=tips, x="total_bill", y="day", hue="sex", kind="violin",
)
# bw와 cut을 이용해서 kde 곡선을 조절할 수 있다
sns.catplot(
    data=tips, x="total_bill", y="day", hue="sex",
    kind="violin", bw_adjust=.5, cut=0,
)
# split=True로 설정시 하나의 violin안에 두 변수를 표현할 수 있다
sns.catplot(
    data=tips, x="day", y="total_bill", hue="sex",
    kind="violin", split=True,
)

# box plot이나 violin plot을 swarm plot과 결합하는 것도 가능
# swarmplot의 ax에 box plot이나 violin plot을 넣어준다
# 이 때, violin plot에서 inner=None을 통해 내부의 boxplot을 제거해준다
g = sns.catplot(data=tips, x="day", y="total_bill", kind="violin", inner=None)
sns.swarmplot(data=tips, x="day", y="total_bill", color="k", size=3, ax=g.ax)
g = sns.catplot(data=tips, x="day", y="total_bill", kind="box")
sns.swarmplot(data=tips, x="day", y="total_bill", color="k", size=3, ax=g.ax)

# barplot
# catplot을 통해서도 barplot을 그릴 수 있다
# 이 때, 추가적으로 95% 신뢰구간을 볼 수 있다
titanic = sns.load_dataset("titanic")
sns.catplot(data=titanic, x="sex", y="survived", hue="class", kind="bar")
# errorbar 옵션을 이용해서 다른 방식으로 분산을 표현할 수 있다
sns.catplot(data=titanic, x="age", y="deck", errorbar="sd", kind="bar")

# Count plot
# Categorical 변수의 빈도를 보기 위해서는 count plot을 사용할 수 있다
sns.catplot(data=titanic, x="deck", kind="count")
sns.catplot(
    data=titanic, y="deck", hue="class", kind="count",
    palette="pastel", edgecolor=".6",
)

# Pointplot
# Pointplot은 Categorical 변수에 따라 다른 변수가 어떻게 변화하는지를 효과적으로 나타낸다
# 이 때 점 추정치 중심으로 95% 신뢰구간이 표현된다
sns.catplot(data=titanic, x="sex", y="survived", hue="class", kind="point")
# marker, linestyles 옵션을 이용해 선과 점 추정치의 형태를 바꿔줄 수 있다
sns.catplot(
    data=titanic, x="class", y="survived", hue="sex",
    palette={"male": "g", "female": "m"},
    markers=["^", "o"], linestyles=["-", "--"],
    kind="point"
)

 

공부하며 어려웠던 내용

 데이터에 따라 가장 적절하게 표현하기 위해 어떻게 시각화할 것인지 많이 생각해봐야 겠다.