[목차]
• 기본 문법
• 한글 설정 방법
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축의 범주별로 행의 개수를 세서 시각화
# 그래프 크기
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: 상관계수 값 표시 여부
'데이터 분석 > Python - 시각화' 카테고리의 다른 글
[Python 시각화 라이브러리, Seaborn] seaborn 팔레트 종류 (0) | 2024.08.29 |
---|---|
[Python 시각화 라이브러리, Plotly] plotly 컬러맵 종류 (1) | 2024.08.27 |
[Python 시각화 라이브러리, Plotly] 그래프별 사용법 정리 (2) | 2024.08.26 |