열심히 코딩 하숭!

데이터 시각화(Matplotlib, Seaborn) | 2주차 | 파이썬 머신러닝 완벽가이드 본문

프로그래밍 언어/python

데이터 시각화(Matplotlib, Seaborn) | 2주차 | 파이썬 머신러닝 완벽가이드

채숭이 2023. 1. 8. 23:46

* 해당 글은 inflearn의 강의 '[개정판] 파이썬 머신러닝 완벽가이드'를 정리한 글입니다.

 

 

 

회색 - 강의 제목

노란색, 주황색 - 강조

민트색 - 발표할 때 짚고 넘어가면 좋을 것 같은 부분

 

 

 


 

 

1일

 

[0:03:04] 시각화를 시작하며

 

- 시각화 몰라도 너무 스트레스 받지 말자!

 

 

[0:11:57] Matplotlib과 Seaborn 개요 및 비교

 

통계적인(statistical) 시각화

- Seaborn

- 히스토그램, 바이올린 플롯, 산포도, 바차트, 분위, 상관 히트맵

 

중간 

- Matplotlib

 

업무 분석(business analysis) 시각화

- Plotly

- 바차트, 라인 플롯, 파이 차트, 영역 차트, 산포도, 방사형 차트, 버블 차트, 깔때기 차트

 


 

맷플롯립(Matplotlib)

- 파이썬 시각화에 큰 공헌을 한 시각화 라이브러리

- 단점: 직관적이지 못한 API, 익숙해지는 데 많은 시간이 필요

 

시본(Seaborn)

- 맷플롯립을 기본으로 하는데, 이보다 적은 양의 코딩으로 수려한 시각화 플롯을 제공

- pandas와 쉽게 연동됨

- 그래도, 시본을 잘 활용하려면 맷플롯립을 어느정도는 알고 있어야 함

 

 

 

[0:11:30] Matplotlib의 이해 - Figure와 Axes

 

matplotlib.pyplot 모듈

- MATLAB 스타일의 interface를 가짐

 

Figure

- 그림을 그리기 위한 Canvas 역할

- 그림판의 크기 등을 조절

 

Axes

- 실제 그림을 그리는 메소드들을 가짐

- x축, y축, title 등의 속성을 설정

- Axis의 복수형이 Axes

 

 

 

 

[0:11:32] Matplotlib Figure와 Axes 실습

 

기본 그래프 코드

import matplotlib.pyplot as plt
#%matplotlib inline -> jupyter notebook이면 생략 가능

plt. figure(figsize=(10,4)) # Figure 객체의 크기 지정
plt.plot([1, 2, 3], [2, 4, 6]) # Axes.plot()함수를 호출하여 그림을 그림
plt.title("Hello plot") # Axes.set_title()함수로 title을 설정함
#plt.show() # Figure.show()를 호출하여 그림을 나타냄 -> jupyter notebook이면 생략 가능

 

Figure 설정

figure = plt.figure(figsize=(10, 4))

-> 크기 지정

plt.figure(figsize=(8,6), facecolor='yellow') # figure의 색 설정
plt.plot([1, 2, 3], [2, 4, 6]) 
plt.title("Hello plot") 
plt.show()

-> figure에만 yellow 색이 적용됨. axes가 그 위에 덮고있는 구조라서, 그래프에는 적용이 되지 않음.

 

 

Axes 보이기

ax = plt.axes()
print(type(ax)

 

 

subplot

- 여러개의 plot을 가지는 figure 만들기

fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(10, 6))

ax1 / ax2

 

 

[0:13:59] Matplotlib의 여러 구성 요소를 이용한 시각화 실습 - 01

 

리스트, numpy 데이터를 이용한 plot

import numpy as np

x_value = [1, 2, 3, 4]
y_value = [2, 4, 6, 8]
x_value = np.array([1, 2, 3, 4])
y_value = np.array([2, 4, 6, 8])

# 입력값으로 파이썬 리스트, numpy array 가능. x축값과 y축값은 모두 같은 크기를 가져야 함. 
plt.plot(x_value, y_value)

-> 입력값으로 파이썬 리스트, numpy array 사용 가능

-> x축값과 y축값은 모두 같은 크기를 가져야 함. 

 

 

DataFrame 데이터를 이용한 plot

import pandas as pd 

df = pd.DataFrame({'x_value':[1, 2, 3, 4],
                   'y_value':[2, 4, 6, 8]})

# 입력값으로 pandas Series 및 DataFrame도 가능. 
plt.plot(df['x_value'], df['y_value'])

-> 입력값으로 pandas Series 및 DataFrame도 사용 가능

 

 

plot 색 변경

plt.plot(x_value, y_value, color='green')

-> plot 색 변경

 

 

그래프 style 변경

plt.plot(x_value, y_value, color='red', marker='o', linestyle='dashed', linewidth=2, markersize=12)

-> 다섯개의 인자들 많이 쓰이니까 알고있기!

 

-> marker : 표시자 / linestyle : 선 방식 / color : 색 종류

 

 

xlabel(), ylabel()

- x축, y축 label 지정

plt.plot(x_value, y_value, color='red', marker='o', linestyle='dashed', linewidth=2, markersize=12)
plt.xlabel('x axis')
plt.ylabel('y axis')
plt.show()

 

xticks(), yticks()

- x, y tick 값 회전하기

x_value = np.arange(0, 100)
y_value = 2*x_value

plt.plot(x_value, y_value, color='green')
plt.xlabel('x axis')
plt.ylabel('y axis')

plt.xticks(ticks=np.arange(0, 100, 5), rotation=90) # x를 5 단위로 나타내기
plt.yticks(rotation=45)

plt.title('Hello plot')
plt.show()

 

xlim(), ylim()

- x, y축의 범위를 제한

x_value = np.arange(0, 100)
y_value = 2*x_value

plt.plot(x_value, y_value, color='green')
plt.xlabel('x axis')
plt.ylabel('y axis')

# x축값을 0에서 50으로, y축값을 0에서 100으로 제한. 
plt.xlim(0, 50)
plt.ylim(0, 100)

plt.title('Hello plot')

plt.show()

 

legend()

- 범례 표기하기

x_value = np.arange(1, 100)
y_value = 2*x_value

plt.plot(x_value, y_value, color='green', label='temp') # 주의: 그림 그리는 plot에 label 이름을 지정하기!
plt.xlabel('x axis')
plt.ylabel('y axis')

plt.legend() # 범례 표현

plt.title('Hello plot')

plt.show()

 

 

 

[0:12:49] Matplotlib의 여러 구성 요소를 이용한 시각화 실습 - 02

 

하나의 Axes에 여러개의 그래프 그리기

- 같은 유형의 그래프

x_value_01 = np.arange(1, 100)
#x_value_02 = np.arange(1, 200)
y_value_01 = 2*x_value_01
y_value_02 = 4*x_value_01

plt.plot(x_value_01, y_value_01, color='green', label='temp_01')
plt.plot(x_value_01, y_value_02, color='red', label='temp_02')
plt.xlabel('x axis')
plt.ylabel('y axis')

plt.legend()

plt.title('Hello plot')

plt.show()

-> 주의 : x가 같아야 함

-> x가 달라도 됨!!!

import numpy as np
import matplotlib.pyplot as plt

x_value_01 = np.arange(1, 100)
x_value_02 = np.arange(1, 200)
y_value_01 = 2*x_value_01
y_value_02 = 4*x_value_02

plt.plot(x_value_01, y_value_01, color='green', label='temp_01')
plt.plot(x_value_02, y_value_02, color='red', label='temp_02')
plt.xlabel('x axis')
plt.ylabel('y axis')

plt.legend()

plt.title('Hello plot')

plt.show()

 

 

 

- 다른 유형의 그래프

x_value_01 = np.arange(1, 10)
#x_value_02 = np.arange(1, 200)
y_value_01 = 2*x_value_01
y_value_02 = 4*x_value_01

plt.plot(x_value_01, y_value_01, color='red', marker='o', linestyle='dashed', linewidth=2, markersize=6, label='temp_01')
plt.bar(x_value_01, y_value_01, color='green', label='temp_02')
plt.xlabel('x axis')
plt.ylabel('y axis')

plt.legend()

plt.title('Hello plot')

plt.show()

 

 

Axes에서 직접 작업

- plt와 함수명의 차이가 있음

figure = plt.figure(figsize=(10, 6))
ax = plt.axes()

ax.plot(x_value_01, y_value_01, color='red', marker='o', linestyle='dashed', linewidth=2, markersize=6, label='temp_01')
ax.bar(x_value_01, y_value_01, color='green', label='temp_02')
ax.set_xlabel('x axis')
ax.set_ylabel('y axis')

ax.legend() # set_legend()가 아니라 legend()임. 
ax.set_title('Hello plot')

plt.show()

 

여러개의 subplots을 가지는 figure를 생성하고, 개별 그래프를 각각 시각화

x_value_01 = np.arange(1, 10)
x_value_02 = np.arange(1, 20)
y_value_01 = 2 * x_value_01
y_value_02 = 2 * x_value_02

fig, (ax_01, ax_02) = plt.subplots(nrows=1, ncols=2, figsize=(12, 6))

ax_01.plot(x_value_01, y_value_01, color='red', marker='o', linestyle='dashed', linewidth=2, markersize=6, label='temp_01')
ax_02.bar(x_value_02, y_value_02, color='green', label='temp_02')

ax_01.set_xlabel('ax_01 x axis')
ax_02.set_xlabel('ax_02 x axis')

ax_01.legend()
ax_02.legend() 

#plt.legend()
plt.show()

- 아래도 같은 결과를 도출해낼 수 있음

import numpy as np

x_value_01 = np.arange(1, 10)
x_value_02 = np.arange(1, 20)
y_value_01 = 2 * x_value_01
y_value_02 = 2 * x_value_02

fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(12, 6))

ax[0].plot(x_value_01, y_value_01, color='red', marker='o', linestyle='dashed', linewidth=2, markersize=6, label='temp_01')
ax[1].bar(x_value_02, y_value_02, color='green', label='temp_02')

ax[0].set_xlabel('ax[0] x axis')
ax[1].set_xlabel('ax[1] x axis')

ax[0].legend()
ax[1].legend() 

#plt.legend()
plt.show()

 

- 응용 : 2개 이상일 때는 2차원배열로 표시

import numpy as np

x_value_01 = np.arange(1, 10)
x_value_02 = np.arange(1, 20)
y_value_01 = 2 * x_value_01
y_value_02 = 2 * x_value_02

fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(12, 6))

ax[0][0].plot(x_value_01, y_value_01, color='red', marker='o', linestyle='dashed', linewidth=2, markersize=6, label='temp_01')
ax[0][1].bar(x_value_02, y_value_02, color='green', label='temp_02')
ax[1][0].plot(x_value_01, y_value_01, color='green', marker='o', linestyle='dashed', linewidth=2, markersize=6, label='temp_03')
ax[1][1].bar(x_value_02, y_value_02, color='red', label='temp_04')

ax[0][0].set_xlabel('ax[0][0] x axis')
ax[0][1].set_xlabel('ax[0][1] x axis')
ax[1][0].set_xlabel('ax[1][0] x axis')
ax[1][1].set_xlabel('ax[1][1] x axis')

ax[0][0].legend()
ax[0][1].legend() 
ax[1][0].legend()
ax[1][1].legend() 

#plt.legend()
plt.show()

 

 

[0:13:33] 정보의 종류에 따른 시각화 유형

 

차트 유형

- 히스토그램 : 많이 쓰임, 분포를 알 수 있음

- 바이올린 플롯 : 히스토그램을 기하학적으로 표현

- 바 플롯 : 수를 표기 (특정값 별 바 플롯 : 한 번에 3개의 값을 비교해볼 수 있음!)

- 스캐터 플롯 : 몰려있는 정도를 알 수 있음, 튀는 데이터 값도 찾아낼 수 있음

- 라인 플롯 : 시계열 데이터 사용할 때 주로 씀

 

 

정보의 종류에 따른 시각화 유형 <- 중요!

 

 

 


 

 

2일

 

 

[0:08:18] Seaborn의 Axis 레벨 함수와 Figure 레벨 함수의 이해

 

Seaborn 소개

- Matplotlib보다 쉽고 간편하다

- pandas와 쉬운 연동이 가능하다

- Matplotlib를 어느정도 알고는 있어야 한다

 

Axes level vs Figure level

- Axes level : 개별 Axes가 plot에 대한 주도적인 역할을 수행한다

- Figure level : FacetGrid라는 클래스에서 개별 Axes 기반의plot을 그릴 수 있는 기능을 통제함?

-> 자동으로 쪼개준다, 아무튼 더 편하다

 

Figure level

- 여러 개의 subplot에서의 plot을 매우 쉽게 생성할 수 있다

- subplot에서 축의 명칭, 타이틀을 별도로 지정하지 않아도, 자동으로 인지하여 생성한다

- 단점 : 새로운 API에 적응해야 함 (강의에서 잘 안 씀! 강의에서는 Axes level 위주로.), 커스터마이징 변경 적용이 어려움

 

 

 

[0:15:24] Seaborn 히스토그램 시각화 실습

 

Histogram

- 연속값에 대한 구간별 도수 분포를 시각화

 

Matplotlib에서 Histogram 출력

### matplotlib histogram
import matplotlib.pyplot as plt

plt.hist(titanic_df['Age'])
#plt.show()

 

Pandas에서 Histogram 출력

# Pandas 에서 hist 함수를 바로 호출할 수 있음. 
titanic_df['Age'].hist()

 

Seaborn에서 Histogram 출력

- distplot() : 예전 histogram(지금은 잘 안 쓰임)

- histplot() : Axes level

- displot() : figure level

 

displot() : 예전 histogram(지금은 잘 안 쓰임, deprecated)

import seaborn as sns
#import warnings
#warnings.filterwarnings('ignore')

sns.distplot(titanic_df['Age'], bins=10, kde=False, rug=True)

 

 

histplot() : Axes level

-  rug 속성 없음

### seaborn histogram
import seaborn as sns

# seaborn에서도 figure로 canvas의 사이즈를 조정
# plt.figure(figsize=(10, 6))
# Pandas DataFrame의 컬럼명을 자동으로 인식해서 xlabel값을 할당. ylabel 값은 histogram일때 Count 할당. 
sns.histplot(titanic_df['Age'], kde=True)
#plt.show()

아래와 같이 사용할 수도 있음

plt.figure(figsize=(12, 6))
sns.histplot(x='Age', data=titanic_df, kde=True, bins=30)

 

displot() : figure level

import seaborn as sns

# seaborn의 figure레벨 그래프는 plt.figure로 figure 크기를 조절할 수 없습니다. 
#plt.figure(figsize=(4, 4))
# Pandas DataFrame의 컬럼명을 자동으로 인식해서 xlabel값을 할당. ylabel 값은 histogram일때 Count 할당. 
sns.displot(titanic_df['Age'], kde=True, rug=True, height=4, aspect=2) # aspect : 가로 세로의 비율
#plt.show()

 

 

[0:08:38] Seaborn Bar 플롯 시각화 실습 - 01

 

countplot()

- 카테고리 값에 대한 건수를 표현

sns.countplot(x='Pclass', data=titanic_df)

 

barplot()

- x축은 이산값 (주로 category 값)

- y축은 연속값 (y값의 평균/총합)

 

#plt.figure(figsize=(10, 6))
# 자동으로 xlabel, ylabel을 x입력값, y입력값으로 설정. 
sns.barplot(x='Pclass', y='Age', data=titanic_df)

-> Pclass에 따른 Age의 평균을 나타냄

 

sns.barplot(x='Pclass', y='Survived', data=titanic_df)

 

- 수직 barplot에 y축을 문자값으로 설정하면 자동으로 수평 barplot으로 변환

sns.barplot(x='Pclass', y='Sex', data=titanic_df)

 

- confidence interval(신뢰구간)을 없애고, color를 통일.

sns.barplot(x='Pclass', y='Survived', data=titanic_df, ci=None, color='green')

 

- 평균이 아니라 총합으로 표현. estimator=sum

sns.barplot(x='Pclass', y='Survived', data=titanic_df, ci=None, estimator=sum)

 

 

[0:10:58] Seaborn Bar 플롯 시각화 실습 - 02

 

hue 인자

- 하나의 정보를 또 추가할 수 있음

# 아래는 Pclass가 X축값이며 hue파라미터로 Sex를 설정하여 개별 Pclass 값 별로 Sex에 따른 Age 평균 값을 구함. 
sns.barplot(x='Pclass', y='Age', hue='Sex', data=titanic_df)

- Age_cat이라는 속성을 새로 추가하여 실습

# 나이에 따라 세분화된 분류를 수행하는 함수 생성. 
def get_category(age):
    cat = ''
    if age <= 5: cat = 'Baby'
    elif age <= 12: cat = 'Child'
    elif age <= 18: cat = 'Teenager'
    elif age <= 25: cat = 'Student'
    elif age <= 35: cat = 'Young Adult'
    elif age <= 60: cat = 'Adult'
    else : cat = 'Elderly'
    
    return cat

# lambda 식에 위에서 생성한 get_category( ) 함수를 반환값으로 지정. 
# get_category(X)는 입력값으로 ‘Age’ 칼럼 값을 받아서 해당하는 cat 반환
titanic_df['Age_cat'] = titanic_df['Age'].apply(lambda x : get_category(x))

 

plt.figure(figsize=(10, 4))
order_columns = ['Baby', 'Child', 'Teenager', 'Student', 'Young Adult', 'Adult', 'Elderly']
sns.barplot(x='Age_cat', y='Survived', hue='Sex', data=titanic_df, order=order_columns)

-> order_columns에 주어진 순서대로 그래프에 표시할 수 있음

 

 

sns.barplot(x='Sex', y='Survived', hue='Age_cat', data=titanic_df)

 

- orient= 'h'를 하면 수평 바 플롯을 그림. 단 이번엔 y축값이 이산형 값이어야 함!

sns.barplot(x='Survived', y='Pclass', data=titanic_df, orient='h')

 

 

[0:07:01] Seaborn Violin 플롯 실습

 

Violin plot

- 연속값의 분포도를 시각화

- 중심에서 4분위를 알 수 있다

 

# Age 컬럼에 대한 연속 확률 분포 시각화 
sns.violinplot(y='Age', data=titanic_df)

 

# x축값인 Pclass의 값별로 y축 값인 Age의 연속분포 곡선을 알 수 있음. 
sns.violinplot(x='Pclass', y='Age', data=titanic_df)

 

# x축인 Sex값 별로 y축값이 Age의 값 분포를 알 수 있음. 
sns.violinplot(x='Sex', y='Age', data=titanic_df)

 

 

[0:18:39] Seaborn에서 subplots을 활용한 시각화 기법 익히기

 

Subplot을 활용해 시각화하기

- 주요 category성 칼럼의 건수를 시각화

cat_columns = ['Survived', 'Pclass', 'Sex', 'Age_cat']

# nrows는 1이고 ncols는 컬럼의 갯수만큼인 subplots을 설정. 
fig, axs = plt.subplots(nrows=1, ncols=len(cat_columns), figsize=(16, 4))

for index, column in enumerate(cat_columns): # enumerate: index랑 column명이 같이 나옴
    print('index:', index)
    # seaborn의 Axes 레벨 function들은 ax인자로 subplots의 어느 Axes에 위치할지 설정. 
    sns.countplot(x=column, data=titanic_df, ax=axs[index])
    if index == 3:
        # plt.xticks(rotation=90)으로 간단하게 할수 있지만 Axes 객체를 직접 이용할 경우 API가 상대적으로 복잡. 
        axs[index].set_xticklabels(axs[index].get_xticklabels(), rotation=90)

-> 마지막 그래프의 x축 label을 rotate함!

 

- 주요 category성 컬럼별로 컬럼값에 따른 생존율 시각화

cat_columns = ['Pclass', 'Sex', 'Age_cat']

# nrows는 1이고 ncols는 컬럼의 갯수만큼인 subplots을 설정. 
fig, axs = plt.subplots(nrows=1, ncols=len(cat_columns), figsize=(16, 4))

for index, column in enumerate(cat_columns):
    print('index:', index)
    # seaborn의 Axes 레벨 function들은 ax인자로 subplots의 어느 Axes에 위치할지 설정. 
    sns.barplot(x=column, y='Survived', data=titanic_df, ax=axs[index])
    if index == 2:
        # plt.xticks(rotation=90)으로 간단하게 할수 있지만 Axes 객체를 직접 이용할 경우 API가 상대적으로 복잡. 
        axs[index].set_xticklabels(axs[index].get_xticklabels(), rotation=90)

 

- subplots를 이용하여 여러 연속형 컬럼값들의 Survived 값에 따른 연속 분포도를 시각화

def show_hist_by_target(df, columns):
    cond_1 = (df['Survived'] == 1)
    cond_0 = (df['Survived'] == 0)
    
    for column in columns:
        fig, axs = plt.subplots(nrows=1, ncols=2, figsize=(12, 4))
        sns.violinplot(x='Survived', y=column, data=df, ax=axs[0] )
        sns.histplot(df[cond_0][column], ax=axs[1], kde=True, label='Survived 0', color='blue')
        sns.histplot(df[cond_1][column], ax=axs[1], kde=True, label='Survived 1', color='red')
        axs[1].legend()
        
cont_columns = ['Age', 'Fare', 'SibSp', 'Parch']
show_hist_by_target(titanic_df, cont_columns)

-> 왼쪽에는 Violin plot / 오른쪽에는 Survived가 0일 때와 1일 때의 Histogram

 

 

 

[0:07:39] Seaborn Box 플롯과 Scatter 플롯 실습

 

box plot

- 4분위를 박스 형태로 표현 (25%, 50%, 75%, outlier)

- x축에 이산값을 부여하면, 이산값에 따른 box plot을 시각화해줌

sns.boxplot(y='Age', data=titanic_df)

 

sns.boxplot(x='Pclass', y='Age', data=titanic_df)

 

scatter plot

- x,y축이 보통 연속형일 때 사용

- 산포도를 시각화함 (얼마나 퍼져있냐)

- 튀는 데이터를 잘 확인할 수 있음

 

sns.scatterplot(x='Age', y='Fare', data=titanic_df)

 

sns.scatterplot(x='Age', y='Fare', data=titanic_df, hue='Pclass')

-> hue를 통해 breakdown(쪼개다) 할 수 있음

 

sns.scatterplot(x='Age', y='Fare', data=titanic_df, hue='Pclass', style='Survived')

-> style 속성을 통해 더 많은 정보를 나타낼 수 있음

 

 

[0:09:05] Seaborn 상관 Heatmap 실습

 

상관 Heatmap

- 컬럼간의 상관도를 Heatmap 형태로 표현

- 수치가 마이너스면 반비례라는 뜻임

- 절대값이 높을 수록 상관관계가 높음

 

titanic_df.corr()

-> 수치로 반환 (숫자형 column에 대해서만)

 

 

plt.figure(figsize=(8, 8))

# DataFrame의 corr()은 숫자형 값만 상관도를 구함. 
corr = titanic_df.corr()

sns.heatmap(corr)

 

plt.figure(figsize=(8, 8))

# DataFrame의 corr()은 숫자형 값만 상관도를 구함. 
corr = titanic_df.corr()

sns.heatmap(corr, annot=True, fmt='.1f',  linewidths=0.5, cmap='YlGnBu')
# annot -> 값 표시 / fmt -> 소수점 자리 설정 / cbar -> 옆에 뜨는 색 표시 / linewidths -> 구분선 표시 / cmap -> 색 설정

-> annot -> 값 표시 / fmt -> 소수점 자리 설정 / cbar -> 옆에 뜨는 색 표시 / linewidths -> 구분선 표시 / cmap -> 색 설정