포스트

Visualization_With_Seaborn

Visualization_With_Seaborn

Visualization_With_Seaborn

1
2
3
4
5
6
import matplotlib.pyplot as plt
%matplotlib
inline
import seaborn as sns
import numpy as np
import pandas as pd
1
sns.set()  # 차트 스타일을 설정하는 seaborn 메서드

Exploring Seaborn Plots

seaborn의 주 목적은 통계 데이터 탐색과 몇 가지 통계 모델 적합에 유용한 다양한 플롯 유형을 생성할 수 있도록 고차원 명령어를 제공하는 것

Histograms, KDE, and densities

1
2
3
4
5
6
7
8
9
data = np.random.multivariate_normal([0, 0], [[5, 2], [2, 2]], size=2000)
data = pd.DataFrame(data, columns=['x', 'y'])
# 데이터 클리닝: 무한 값 대체
data.replace([np.inf, -np.inf], np.nan, inplace=True)
data.dropna(inplace=True)

# 분포를 시각화하기 위한 히스토그램
for col in 'xy':
    plt.hist(data[col], density=True, alpha=0.5)

png

1
2
# 분포 시각화를 위한 커널 밀도 추정치
sns.kdeplot(data=data, fill=True);

png

1
2
# 2차원 커널 밀도 그래프
sns.kdeplot(data, x='x', y='y');

png

1
2
3
# 결합분포와 한계분포
with sns.axes_style('white'):
    sns.jointplot(data=data, x="x", y="y", kind='kde');

png

1
2
3
# 육각형 기반
with sns.axes_style('white'):
    sns.jointplot(data=data, x="x", y="y", kind='hex');

png

Pair plots

1
2
iris = sns.load_dataset("iris")
iris.head()
sepal_lengthsepal_widthpetal_lengthpetal_widthspecies
05.13.51.40.2setosa
14.93.01.40.2setosa
24.73.21.30.2setosa
34.63.11.50.2setosa
45.03.61.40.2setosa
1
2
# 표번 사이 다차원 관계 시각화
sns.pairplot(iris, hue='species', height=2.5);

png

Faceted histograms

1
2
tips = sns.load_dataset('tips')
tips.head()
total_billtipsexsmokerdaytimesize
016.991.01FemaleNoSunDinner2
110.341.66MaleNoSunDinner3
221.013.50MaleNoSunDinner3
323.683.31MaleNoSunDinner2
424.593.61FemaleNoSunDinner4
1
2
3
4
tips['tip_pct'] = 100 * tips['tip'] / tips['total_bill']

grid = sns.FacetGrid(tips, row="sex", col="time", margin_titles=True)
grid.map(plt.hist, "tip_pct", bins=np.linspace(0, 40, 15));

png

범주형 플롯 catplots

1
2
3
with sns.axes_style(style='ticks'):
    g = sns.catplot(x="day", y="total_bill", hue="sex", data=tips, kind="box")
    g.set_axis_labels("Day", "Total Bill");

png

Joint distributions

1
2
3
# 결합 분포 플롯
with sns.axes_style('white'):
    sns.jointplot(x="total_bill", y="tip", data=tips, kind='hex')

png

1
2
# 자동 커널 밀도 추정과 회귀 분석 수행
sns.jointplot(x="total_bill", y="tip", data=tips, kind='reg');

png

Bar plots

1
2
planets = sns.load_dataset('planets')
planets.head()
methodnumberorbital_periodmassdistanceyear
0Radial Velocity1269.3007.1077.402006
1Radial Velocity1874.7742.2156.952008
2Radial Velocity1763.0002.6019.842011
3Radial Velocity1326.03019.40110.622007
4Radial Velocity1516.22010.50119.472009
1
2
3
4
5
# 요인 플롯의 특별한 경우로 사용된 히스토그램
with sns.axes_style('white'):
    g = sns.catplot(x="year", data=planets, aspect=2,
                    kind="count", color='steelblue')
    g.set_xticklabels(step=5)

png

1
2
3
4
5
# 연도 및 유형별로 발견된 행성 수
with sns.axes_style('white'):
    g = sns.catplot(x="year", data=planets, aspect=4.0, kind='count',
                    hue='method', order=range(2001, 2015))
    g.set_ylabels('Number of Planets Discovered')

png

Example: Exploring Marathon Finishing Times

1
2
data = pd.read_csv('./marathon-data.csv')
data.head()
agegendersplitfinal
033M01:05:3802:08:51
132M01:06:2602:09:28
231M01:06:4902:10:42
338M01:06:1602:13:45
431M01:06:3202:13:59
1
2
# 기본적으로 Pandas는 시간 열을 파이썬 문자열로 적재
data.dtypes
1
2
3
4
5
age        int64
gender    object
split     object
final     object
dtype: object
1
2
3
4
5
6
7
8
9
10
11
import datetime


def convert_time(s):
    h, m, s = map(int, s.split(':'))
    return datetime.timedelta(hours=h, minutes=m, seconds=s)


data = pd.read_csv('./marathon-data.csv',
                   converters={'split': convert_time, 'final': convert_time})
data.head()
agegendersplitfinal
033M0 days 01:05:380 days 02:08:51
132M0 days 01:06:260 days 02:09:28
231M0 days 01:06:490 days 02:10:42
338M0 days 01:06:160 days 02:13:45
431M0 days 01:06:320 days 02:13:59
1
data.dtypes
1
2
3
4
5
age                 int64
gender             object
split     timedelta64[ns]
final     timedelta64[ns]
dtype: object
1
2
3
4
# Seaborn 플로팅을 목적으로 시간을 초로 제공하는 열 추가
data['split_sec'] = data['split'].dt.total_seconds()
data['final_sec'] = data['final'].dt.total_seconds()
data.head()
agegendersplitfinalsplit_secfinal_sec
033M0 days 01:05:380 days 02:08:513938.07731.0
132M0 days 01:06:260 days 02:09:283986.07768.0
231M0 days 01:06:490 days 02:10:424009.07842.0
338M0 days 01:06:160 days 02:13:453976.08025.0
431M0 days 01:06:320 days 02:13:593992.08039.0
1
2
3
4
5
# 데이터 확인을 위한 플로팅
with sns.axes_style('white'):
    g = sns.jointplot(x="split_sec", y="final_sec", data=data, kind='hex')
    g.ax_joint.plot(np.linspace(4000, 16000),
                    np.linspace(8000, 32000), ':k')

png

1
2
3
# 주자가 네거티브 스플릿 주자인지 포지티브 스플릿 주자인지 정도를 측정하는 열
data['split_frac'] = 1 - 2 * data['split_sec'] / data['final_sec']
data.head()
agegendersplitfinalsplit_secfinal_secsplit_frac
033M0 days 01:05:380 days 02:08:513938.07731.0-0.018756
132M0 days 01:06:260 days 02:09:283986.07768.0-0.026262
231M0 days 01:06:490 days 02:10:424009.07842.0-0.022443
338M0 days 01:06:160 days 02:13:453976.08025.00.009097
431M0 days 01:06:320 days 02:13:593992.08039.00.006842
1
2
3
# 만든 열을 통한 분포도
sns.histplot(data['split_frac'], kde=False);
plt.axvline(0, color="k", linestyle="--");

png

1
2
# 네거티브 스플릿 수
sum(data.split_frac < 0)
1
251
1
2
3
4
5
# 스플릿 정도와 다른 변수들 사이에 상관관계 확인
g = sns.PairGrid(data, vars=['age', 'split_sec', 'final_sec', 'split_frac'],
                 hue='gender', palette='RdBu_r')
g.map(plt.scatter, alpha=0.8)
g.add_legend();

png

1
2
3
4
# 남성과 여성 사이 차이
sns.kdeplot(data.split_frac[data.gender == 'M'], label='men', fill=True)
sns.kdeplot(data.split_frac[data.gender == 'W'], label='women', fill=True)
plt.xlabel('split_frac');

png

1
2
3
# 나이의 함수로 분포 비교
sns.violinplot(x="gender", y="split_frac", data=data, hue="gender",
               palette=["lightblue", "lightpink"], legend=False);

png

1
2
data['age_dec'] = data.age.map(lambda age: 10 * (age // 10))
data.head()
agegendersplitfinalsplit_secfinal_secsplit_fracage_dec
033M0 days 01:05:380 days 02:08:513938.07731.0-0.01875630
132M0 days 01:06:260 days 02:09:283986.07768.0-0.02626230
231M0 days 01:06:490 days 02:10:424009.07842.0-0.02244330
338M0 days 01:06:160 days 02:13:453976.08025.00.00909730
431M0 days 01:06:320 days 02:13:593992.08039.00.00684230
1
2
3
4
5
6
7
8
# 나이 함수로 바이올린 플롯 비교
men = (data.gender == 'M')
women = (data.gender == 'W')

with sns.axes_style(style=None):
    sns.violinplot(x="age_dec", y="split_frac", hue="gender", data=data,
                   split=True, inner="quartile",
                   palette=["lightpink", "lightblue"]);

png

1
2
# 데이터 표본이 작아 80대 이상 여성의 능력치 이상
(data.age > 80).sum()
1
7
1
2
3
4
# 데이터에 선형 회귀 모형 자동 적합
g = sns.lmplot(x='final_sec', y='split_frac', col='gender', data=data,
               markers=".", scatter_kws=dict(color='c'))
g.map(plt.axhline, y=0.1, color="k", ls=":");

png

이 기사는 저작권자의 CC BY-NC 4.0 라이센스를 따릅니다.