[Python 시각화 라이브러리, seaborn] 그래프별 사용법 정리

데이터 분석/Python - 시각화

[Python 시각화 라이브러리, seaborn] 그래프별 사용법 정리

해리누나 2024. 8. 28. 23:24
반응형

 


 [목차]
기본 문법
한글 설정 방법
1. 막대 그래프
- MaxNLocator
2. 선 그래프
- 겹치지 않게 범주별 색 지정하는 법
3. 산점도 그래프
- 선형 회귀선 추가
4. 히스토그램
5. 박스 플롯(상자 수염 차트, 상자 그림)
6. 파이 차트
7. 히트맵

 

📝matplotlib

- 파이썬의 시각화를 위한 다목적 라이브러리

- 유연한 커스텀이 가능하나 코드가 길고 어렵다

 

📝seaborn

- matplotlib를 기반으로 하는 파이썬 데이터 시각화 라이브러리

- matplotlib을 좀 더 쉽게 시각화하는 라이브러리

- 시각화할 때 seaborn을 matplotlib과 함께 사용하는 경우가 많다.

 

기본 문법

import matplotlib.pyplot as plt
import seaborn as sns

# 그래프 크기 설정
plt.figure(figsize=(가로길이, 세로길이))

# Seaborn으로 그래프 그리기
sns.그래프종류plot(data=데이터, x='X축 컬럼', y='Y축 컬럼', hue='범례 컬럼')

# 제목 및 라벨 설정
plt.title('제목')
plt.xlabel('X축 라벨')
plt.ylabel('Y축 라벨')

# 범례 위치와 각 축 레이블 각도 설정
plt.legend(loc='범례 위치')
plt.xticks(rotation=각도)
plt.yticks(rotation=각도)

# 그래프 출력
plt.show()

📖 그래프 종류

  •  막대그래프 - sns.barplot

  •  선 그래프 - sns.lineplot

  •  산점도 그래프 - sns.scatterplot

  •  히스토그램 - sns.histplot

  •  박스 플롯 - sns.boxplot

  •  파이 차트 - seaborn 자체 지원 ❌ (matplotlib 사용 필요)

  •  히트맵 - sns.heatmap

※ 한글 폰트 설정을 해줘야 한글이 깨지지 않는다.

※ 그래프 크기는 인치(inch) 단위로 설정된다.

※ seaborn에서는 palette 옵션이 hue 변수가 있을 때 유효하다.
   (hue: 데이터를 범주형으로 나누어 서로 다른 색상으로 표현)

 

한글 설정

!sudo apt-get install -y fonts-nanum
!sudo fc-cache -fv
!rm ~/.cache/matplotlib -rf
# 폰트 설치가 끝났으면, 세션 다시 시작 후
# 아래 코드로 폰트를 적용해준다.
plt.rc('font', family='NanumGothic')

 

 

1. 막대 그래프

기본 막대그래프

region_top10 = data.groupby('시군명').size().reset_index(name = '유기동물 수').sort_values(by = '유기동물 수', ascending = False).head(10)
# 그래프 크기 설정
plt.figure(figsize=(7, 5))  

# Seaborn으로 막대 그래프 그리기
sns.barplot(data=region_top10, x='시군명', y='유기동물 수')
# 그래프 제목 설정
plt.title('유기동물 발견 지역 상위10')
# 그래프 출력
plt.show()

 

막대그래프 - 스타일 커스터마이징

# 그래프 크기
plt.figure(figsize=(7, 5))  

# Seaborn으로 막대 그래프
sns.barplot(data=region_top10, x='시군명', y='유기동물 수', color='#B1510F')

# 제목과 레이아웃 설정
plt.title('상위 10 지역별 유기동물 수', fontsize=13, loc='center', pad=10)
plt.xlabel('시군명', fontsize=10)
plt.ylabel('유기동물 수', fontsize=10)

# 배경색 
plt.gca().set_facecolor((240/255, 240/255, 240/255, 0.5))  # 그래프 내부 배경색
plt.gcf().set_facecolor('#EBE6E1') # 그래프 외부 배경색

plt.show()

※ pad: 제목과 그래프의 상단 사이의 여백을 지정

※ x축과 y축의 그래프와의  여백 지정은 labelpad로 가능

※ 위에서는 각 그룹별로 행을 직접 뽑아서 그래프를 그렸는데

※ seaborn에서는 countplot을 제공하고 있어서 이거 사용하면 되긴 하다.

※ sns.countplot: x축의 범주별로 행의 개수를 세서 시각화

 

countplot 사용

# 그래프 크기
plt.figure(figsize=(10, 5))  

# Seaborn으로 막대 그래프
sns.countplot(data=data, x='시군명', color='#B1510F')

# 제목과 레이아웃 설정
plt.title('지역별 유기동물 수', fontsize=13, loc='center', pad=10)
plt.xlabel('시군명', fontsize=10)
plt.ylabel('유기동물 수', fontsize=10)
plt.xticks(rotation=70)

# 배경색 
plt.gca().set_facecolor((240/255, 240/255, 240/255, 0.5))  # 그래프 내부 배경색
plt.gcf().set_facecolor('#EBE6E1') # 그래프 외부 배경색

plt.show()

 

범례 적용

plt.figure(figsize=(7, 5))  
sns.barplot(data=data, x='동물종류', y='체중(kg)', hue='성별', errorbar=None)

plt.title("동물 종류별 평균 체중", fontsize=14, pad=8)
plt.xlabel('동물 종류', fontsize=12, labelpad=7)
plt.ylabel('평균 체중(kg)', fontsize=12, labelpad=7)

# 범례 설정
legend_labels = {'F': '암컷', 'M': '수컷', 'Q': '알 수 없음'}
handles, labels = plt.gca().get_legend_handles_labels()
new_labels = [legend_labels[label] for label in labels]
plt.legend(handles, new_labels, title='동물 성별', title_fontsize='10', fontsize='9')

plt.show()

plt.gca().get_legend_handles_labels():

  • plt.gca(): 현재의 축(Axis)을 가져오는 함수
  • get_legend_handles_labels()는 현재 축에서 범례의 핸들(handles)과 라벨(labels)을 가져옴
  • handles: 그래프의 범례 항목(막대, 선 등)을 가리키는 객체
  • labels: 범례에 표시된 텍스트(라벨) / (원래 지정한 레이블값 'F', 'M', ...)

 


2. 선 그래프

기본 선 그래프

plt.figure(figsize=(15, 6))
sns.lineplot(data=day, x='접수일자', y='카운트')

plt.title('일별 유기동물 수 추이', fontsize=16, pad=15)
plt.xlabel('접수일자', fontsize=12, labelpad=10)
plt.ylabel('유기동물 수', fontsize=12, labelpad=10)

# x축 라벨 각도 조정
plt.xticks(rotation=90)
plt.show()

※ 모든 x축 값이 다 적히는 바람에 각도 조정을 해도 굉장히 지저분한 느낌이 드는데

※ 라벨에 개수를 제한해 두는 방법이 있다.

 

✏️ MaxNLocator 사용하기

from matplotlib.ticker import MaxNLocator

plt.figure(figsize=(15, 6))
sns.lineplot(data=day, x='접수일자', y='카운트')

plt.title('일별 유기동물 수 추이', fontsize=16, pad=15)
plt.xlabel('접수일자', fontsize=12, labelpad=10)
plt.ylabel('유기동물 수', fontsize=12, labelpad=10)
plt.xticks(rotation=90)

# x축에 표시할 최대 틱 개수 설정
plt.gca().xaxis.set_major_locator(MaxNLocator(nbins=10))  # 최대 10개의 라벨 표시
plt.show()

 

선 그래프 - 스타일 커스터마이징

plt.figure(figsize=(15, 6))
# 선 색 및 굵기 지정
sns.lineplot(data=day, x='접수일자', y='카운트', color='#B1510F', linewidth=2)

plt.title('일별 유기동물 수 추이', fontsize=14, pad=8, loc='center')
plt.xlabel('날짜', fontsize=12, labelpad=10)
plt.ylabel('유기동물 수', fontsize=12, labelpad=10)

plt.gca().set_facecolor((240/255, 240/255, 240/255, 0.5)) 
plt.gcf().set_facecolor('#EBE6E1') 

plt.xticks(rotation=45)
plt.gca().xaxis.set_major_locator(MaxNLocator(nbins=10))  # 최대 10개의 라벨 표시
plt.show()

 

범례 적용

plt.figure(figsize=(12, 6))
palette = sns.color_palette("tab20")
sns.lineplot(data=region, x='접수월', y='유기동물 수', hue='시군명', palette=palette, linewidth=1.5)

plt.title('월별 유기동물 수 추이', fontsize=14, pad=8, loc='center')
plt.xlabel('월', fontsize=12, labelpad=10)
plt.ylabel('유기동물 수', fontsize=12, labelpad=10)

plt.legend(title='시군명', title_fontsize='10', fontsize='9')
plt.show()

※ 색상 팔레트 지정은 sns.color_palette("팔레트명")

※ 팔레트가 가진 색보다 범주가 많을 경우

'The palette list has fewer values (20) than needed (31) and will cycle, which may produce an uninterpretable plot.' 이런 경고가 뜰 텐데

※ palette = sns.color_palette("tab20", n_colors=region['범례로 지정할 컬럼명'].nunique()) 이렇게 범주의 수만큼 색을 가져오겠다 지정하면 경고가 뜨지 않는다.

※ 하지만 어차피 각 팔레트는 가진 색의 수가 정해져 있어서,  색상 수보다 범주의 수가 많을 경우 이미 사용된 색을 다시 사용하게 된다.

plt.figure(figsize=(12, 6))

# 팔레트에서 범례 값 별로 색을 지정하게
palette = sns.color_palette("tab20", n_colors=region['시군명'].nunique())
sns.lineplot(data=region, x='접수월', y='유기동물 수', hue='시군명', palette=palette, linewidth=1.5)

plt.title('월별 유기동물 수 추이', fontsize=14, pad=8, loc='center')
plt.xlabel('월', fontsize=12, labelpad=10)
plt.ylabel('유기동물 수', fontsize=12, labelpad=10)

# 범례 이동
plt.legend(title='시군명', title_fontsize='10', fontsize='9', loc='center', bbox_to_anchor=(1.12, 0.5))

plt.show()

※ 범례를 위치로 따로 설정해두지 않으면 그래프와 겹쳐진 상태로 그려지게 되는데

※ loc와 bbox_to_anchor로 알맞은 위치를 정해주면 된다.

 

✏️ 겹치지 않게 범주별 색 지정하는 법

[방법 1] 팔레트 결합하기

# 팔레트 결합
palette = sns.color_palette("tab20", 20) + sns.color_palette("Set3", 11) 

plt.figure(figsize=(12, 6))
sns.lineplot(data=region, x='접수월', y='유기동물 수', hue='시군명', palette=palette, linewidth=1.5)
plt.title('월별 유기동물 수 추이', fontsize=14, pad=8, loc='center')
plt.xlabel('월', fontsize=12, labelpad=10)
plt.ylabel('유기동물 수', fontsize=12, labelpad=10)
plt.legend(title='시군명', title_fontsize='10', fontsize='9', loc='center left', bbox_to_anchor=(1, 0.5))
plt.show()

※ 필요한 만큼 여러 팔레트에서 색상을 뽑아오면 된다.

 

[방법 2] 팔레트 결합하기

palette = sns.color_palette("husl", n_colors=region['시군명'].nunique())

plt.figure(figsize=(12, 6))
sns.lineplot(data=region, x='접수월', y='유기동물 수', hue='시군명', palette=palette, linewidth=1.5)
plt.title('월별 유기동물 수 추이', fontsize=14, pad=8, loc='center')
plt.xlabel('월', fontsize=12, labelpad=10)
plt.ylabel('유기동물 수')
plt.legend(title='시군명', title_fontsize='10', fontsize='9', loc='center left', bbox_to_anchor=(1, 0.5))
plt.show()

※ 'husl', 'hls' 팔레트는 사용자가 필요한 색상 수에 맞게 자동으로 색상을 생성해준다.

 


3. 산점도 그래프

산점도 그래프는 그 유명한 펭귄 데이터를 활용해보자.

searborn을 통해 데이터셋을 쉽게 가져올 수 있다

펭귄 데이터 컬럼 정보

import seaborn as sns

df = sns.load_dataset('penguins')

 

기본 산점도 그래프

 

plt.figure(figsize=(7, 5))

# 산점도 그래프 
sns.scatterplot(data=penguins, x='bill_length_mm', y='bill_depth_mm', color='darkblue')
plt.title('부리 길이에 따른 부리 깊이')
plt.xlabel('부리 길이(mm)')
plt.ylabel('부리 깊이(mm)')

plt.show()

 

산점도 그래프 - 스타일 커스터마이징

plt.figure(figsize=(7, 5))

sns.scatterplot(data=penguins, x='bill_length_mm', y='bill_depth_mm', 
                color='#F8766D', s=64)  # 점의 색상과 크기(s) 설정

plt.title('부리 길이에 따른 부리 깊이', fontsize=14, pad=10, loc='center')
plt.xlabel('부리 길이(mm)', fontsize=12, labelpad=8)
plt.ylabel('부리 깊이(mm)', fontsize=12, labelpad=8)

# 그래프 배경색 
plt.gca().set_facecolor('white') # 내부
plt.gcf().set_facecolor('white') # 외부

plt.show()

 

컬럼값에 따른 점의 크기 변경

# 무게 컬럼에 Nan값이 존재해 해당 행 제거
penguins = penguins.dropna()

plt.figure(figsize=(7, 5))
# body_mass_g에 따라 점 크기 조절
sns.scatterplot(data=penguins, x='bill_length_mm', y='bill_depth_mm', 
                size=penguins['body_mass_g'], sizes=(20, 200), color='#F8766D', legend=False)

plt.title('부리 길이에 따른 부리 깊이')
plt.xlabel('부리 길이(mm)')
plt.ylabel('부리 깊이(mm)')

plt.show()

※ size에 어떤 컬럼값에 따라 크기를 변환시켜줄 것인지 적어주면 된다.

※ sizes=(최소값,최대값): 점의 크기에 제한 두기

 

범례 적용

plt.figure(figsize=(7, 5))

# 범례에 따라 색상이 변경된다.
sns.scatterplot(data=penguins, x='bill_length_mm', y='bill_depth_mm', hue='sex', s=64)  # s는 점의 크기

plt.title('부리 길이에 따른 부리 깊이')
plt.xlabel('부리 길이(mm)')
plt.ylabel('부리 깊이(mm)')

plt.show()

※ 아니 저 희멀건한 색 뭔데....

※ 원래 저랬는지 기억은 안나지만, 범주별 차이가 선명하도록 색을 지정해주자.

 

palette = sns.color_palette("Set2",2)
plt.figure(figsize=(7, 5))

sns.scatterplot(data=penguins, x='bill_length_mm', y='bill_depth_mm', 
                hue='sex', s=64, palette=palette)
                
plt.title('부리 길이에 따른 부리 깊이')
plt.xlabel('부리 길이(mm)')
plt.ylabel('부리 깊이(mm)')

plt.show()

 

※ seaborn에서 scatterplot 사용 시, color와 hue 인자를 함께 사용하면 hue 인자가 우선시되어 색상이 지정된다고 한다.
※ 즉 color 인자는 무시되니 palette를 사용해주자.

 

점 스타일 지정하기

plt.figure(figsize=(7, 5))
scatter_plot = sns.scatterplot(data=penguins, x='bill_length_mm', y='bill_depth_mm',
                               hue='island', style='sex', palette='Set2',
                               s=70) 

scatter_plot.set_xlabel('부리 길이(mm)')
scatter_plot.set_ylabel('부리 깊이(mm)')
scatter_plot.legend(title='서식지', bbox_to_anchor=(1.00, 1.02), loc='upper left')

plt.title('부리 길이에 따른 부리 깊이')
plt.show()

 

그래프 나눠서 나타내기

한 컬럼을 기준으로 그래프를 나눠서 그리는 방법 👇

 

g = sns.FacetGrid(penguins, col='island', hue='sex', palette='Set2', col_wrap=3, height=5)

# 산점도 그래프
g.map(sns.scatterplot, 'bill_length_mm', 'bill_depth_mm', s=70)

# 레이블 설정
g.set_axis_labels('부리 길이(mm)', '부리 깊이(mm)')
g.set_titles(col_template="{col_name}")

# 제목 설정
plt.subplots_adjust(top=0.85)
g.fig.suptitle('부리 길이에 따른 부리 깊이', fontsize=16)

# 범례 위치 
g.add_legend(title='성별', bbox_to_anchor=(0.94, 0.9), loc='upper left')

plt.show()

※ seaborn의 FacetGrid를 사용해 가능하다고 한다.

 

선형 회귀선 추가하기

※ seaborn의 regplot 을 사용해야 한다.

plt.figure(figsize=(7, 5))

# 산점도와 선형 회귀선
sns.regplot(data=penguins, x='bill_length_mm', y='bill_depth_mm', 
            scatter_kws={'color': '#F8766D', 's': 64},  # 점의 색상과 크기 설정
            line_kws={'color': '#FA9890', 'linewidth': 2})  # 회귀선의 색상과 두께 설정

# 그래프 제목 및 레이아웃 설정
plt.title('부리 길이에 따른 부리 깊이')
plt.xlabel('부리 길이(mm)')
plt.ylabel('부리 깊이(mm)')

plt.show()

※ 회귀선 주변에 반투명한 영역?이 표시되는데 이는 신뢰 구간 영역이다.

📝신뢰 구간 영역이란?

- 회귀선의 추정값이 해당 구간 내에 있을 확률을 나타낸다.

- 제거하고 싶다면 ci=None!

 

신뢰구간 제거

sns.regplot(data=penguins, x='bill_length_mm', y='bill_depth_mm', 
            scatter_kws={'color': '#F8766D', 's': 64},
            line_kws={'color': '#FA9890', 'linewidth': 2},
            ci=None)

 

 

※ 범례가 있는 상태에서 회귀선을 각 범주별로 지정해주고 싶은 경우 👇

 

# lmplot을 사용하면 된다.
plt.figure(figsize=(7, 5))

sns.lmplot(data=penguins, x='bill_length_mm', y='bill_depth_mm', 
           hue='sex', palette='Set2', 
           aspect=1.4, height=5, ci=None)

plt.title('부리 길이에 따른 부리 깊이')
plt.xlabel('부리 길이(mm)')
plt.ylabel('부리 깊이(mm)')

plt.show()

 


4. 히스토그램

기본 히스토그램

plt.figure(figsize=(6, 5))

# 히스토그램 
sns.histplot(data=animals_weight, x='체중(kg)')
plt.title('히스토그램')

plt.show()

 

히스토그램- 스타일 커스터마이징

 

plt.figure(figsize=(6, 5))
sns.histplot(data=animals_weight, x='체중(kg)', color='#F8766D', edgecolor='gray', linewidth=1)
plt.title('히스토그램', loc='center')
plt.ylabel('유기동물 수')

plt.show()

 


5. 박스 플롯(상자 수염 차트, 상자 그림)

기본 박스 플롯

plt.figure(figsize=(7, 5))
# 박스 플롯
sns.boxplot(data=data, x='체중(kg)')
plt.title('유기동물 몸무게 박스 플롯')

plt.show()

 

박스 플롯- 스타일 커스터마이징

plt.figure(figsize=(6, 5))

sns.boxplot(data=data, x='체중(kg)', color=sns.color_palette('Set2')[0])
plt.title('유기동물 몸무게 박스 플롯', loc='center')

plt.show()

※ hue인자를 사용하지 않아 palette = palette 명을 사용할 수는 없으나 위처럼 팔레트에서 색상을 가져와서 color로 사용할 수 있다.


6. 파이 차트

기본 파이 차트

※ seaborn은 파이 차트를 직접적으로 지원하지 않아 matplotlib을 사용하여 파이 차트를 생성해야 한다.

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

plt.pie(age['비율'], labels=age['나이'], autopct='%1.1f%%', colors=sns.color_palette('Set2'))
plt.title('유기동물 나이별 비율')

plt.show()

※ autopct를 지정해줘야 % 글자가 적혀지게 된다.

※ 레이블이 겹쳐지는 경우 레비을을 범례에 표시하면 된다. 👇

 

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

plt.pie(age['비율'], labels=None, autopct='%1.1f%%', colors=sns.color_palette('Set2'))
plt.legend(labels=age['나이'], loc='center left', bbox_to_anchor=(1, 0.5))
plt.title('유기동물 나이별 비율')

plt.show()

 

파이 차트- 스타일 커스터마이징

wedgeprops={'width': 0.7, 'edgecolor': 'w', 'linewidth': 1.2}

plt.pie(age['비율'], labels=None, autopct='%.1f%%', startangle=270, counterclock=False, colors=sns.color_palette('Set2'), wedgeprops=wedgeprops)
plt.legend(labels=age['나이'], loc='center left', bbox_to_anchor=(1, 0.5), title='나이')

plt.title('유기동물 나이별 비율')
plt.show()

※ counterclock = False : 시계방향 / True: 반시계방향

※ wedgeprops

- width: 구멍을 제외한 원, 즉 부채꼴 영역의 너비

- edgecolor: 테두리 색상

- linewidth: 테두리 굵기

wedgeprops={'width': 0.7, 'edgecolor': 'w', 'linewidth': 1.2}

plt.pie(age['비율'], labels=None, autopct='%.1f%%', startangle=270, counterclock=False, colors=sns.color_palette('Set2'), 
        wedgeprops=wedgeprops, shadow=True)
plt.legend(labels=age['나이'], loc='center left', bbox_to_anchor=(1, 0.5), title='나이')

plt.title('유기동물 나이별 비율')
plt.show()

※ shadow = True로 그림자를 넣어줄 수도 있다.

 

wedgeprops={'width': 0.7, 'edgecolor': 'w', 'linewidth': 1.2}
explode = [0.0] + [0.1] + [0.0] * 17

plt.pie(age['비율'], labels=None, autopct='%.1f%%', counterclock=False, colors=sns.color_palette('Set2'), 
        wedgeprops=wedgeprops, explode = explode, shadow=True)
plt.legend(labels=age['나이'], loc='center left', bbox_to_anchor=(1, 0.5), title='나이')

plt.title('유기동물 나이별 비율')
plt.show()

※ explode를 통해 특정 부채꼴이 파이 차트의 중심에서 벗어나게 설정하는 것도 가능하다.

※ 예) 0.1: 반지름의 10%만큼 벗어나도록 지정하겠다는 뜻

 


7. 히트맵

히트맵으로 상관계수 그래프를 그려보자.

데이터는 타이타닉 탑승자 데이터를 활용했다.

펭귄데이터와 마찬가지로 seaborn을 통해 바로 데이터를 가져올 수 있다.

import seaborn as sns

titanic = sns.load_dataset('titanic')
titanic = titanic[['survived','pclass','age','sibsp','fare']].corr()

 

기본 히트맵

sns.heatmap(data=corr_matrix3)
plt.title('타이타닉 생존자 상관계수 그래프')

plt.show()

 

히트맵- 스타일 커스터마이징

sns.heatmap(corr_matrix3, annot=True, cmap='Purples', fmt='.2f', linewidths=0.5)
plt.title('타이타닉 생존자 상관계수 그래프')

plt.show()

※  annot: 상관계수 값 표시 여부

 

 


 

728x90
반응형