본문 바로가기
혼자 공부하는 데이터 분석

5장 데이터 시각화하기

by chaechaekim 2023. 5. 29.

05-1 맷플롯립 기본 요소 알아보기

 

Figure 객체

Figure(피겨): 모든 그래프 구성 요소를 담고 있는 최상위 객체

→ scatter() 함수로 산점도를 그릴 때 자동으로 피겨 객체가 생성

 

지난 실습 데이터 ns_book7.csv 파일 다운

import gdown

gdown.download('https://bit.ly/3pK7iuu', 'ns_book7.csv', quiet=False)

 

판다스를 임포트하여 판다스 데이터프레임으로 불러오고, head() 메서드로 상위 5개 행 출력

import pandas as pd

ns_book7 = pd.read_csv('ns_book7.csv', low_memory=False)
ns_book7.head()

 

맷플롯립을 임포트한 후 투명도를 0.1로 지정하고 scatter() 함수로 '도서권수' 열을 x축, '대출건수'열을 y축으로 그리기

import matplotlib.pyplot as plt

plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
plt.show()

 

  • 그래프 크기 바꾸기: figsize 매개변수

figsize 매개변수에 그래프의 크기를 튜플로 지정할 수 있다.

→ 기본 그래프 크기는 (6, 4)이고 각각 너비와 높이에 해당

 

figsize 매개변수를 (9, 6)으로 지정하여 산점도 크게 그리기

plt.figure(figsize=(9, 6))
plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
plt.show()

 

  • 그래프 실제 크기 확인하기

DPI(dot per inch): 1인치를 몇 개의 점(픽셀)으로 표현하는지 나타낸다.

→ DPI에 따라 화면에 그려지는 그래프 크기가 달라진다.

 

맷플롯립의 기본 DPI는 72이므로 다음처럼 두 픽셀 값을 72로 나누어 figsize 매개변수에 전달

plt.figure(figsize=(900/72, 600/72))
plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
plt.show()

 

타이트 레이아웃: 그래프 주변에 공백을 최소화

→ 사용하지 않으려면 bbox_inches 옵션을 None으로 지정해야 한다.

%config InlineBackend.print_figure_kwargs = {'bbox_inches': None}
plt.figure(figsize=(900/72, 600/72))
plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
plt.show()

원래대로 타이트한 레이아웃으로 되돌아가기

%config InlineBackend.print_figure_kwargs = {'bbox_inches': 'tight'}

 

  • 그래프 크기 바꾸기: dpi 매개변수

 

DPI 기본값인 72에서 144로 두 배 늘리기

plt.figure(dpi=144)
plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
plt.show()

*인치당 칙셀 수가 두 배로 늘어나기 때문에 그래프 안의 모든 구성 요소도 함께 커진다.

 

rcParams 객체

: 맷플롯립 그래프의 기본값을 관리하는 객체

 

  • DPI 기본값 바꾸기

: 기본 그래프 해상도를 높이기 위해서

figure 객체의 DPI 기본값을 100으로 바꾸기

plt.rcParams['figure.dpi'] = 100

 

  • 산점도 마커 모양 바꾸기

산점도 그래프 마커 기본값 확인하기: rcParams 객체 속성 scatter.marker로 지정

plt.rcParams['scatter.marker']

 

마커 별 모양으로 지정하기

plt.rcParams['scatter.marker'] = '*'

 

산점도가 별 모양으로 그려지는지 확인

plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
plt.show()

 

기본값을 수정하는 대신 scatter() 함수의 marker 매개변수로 마커 모양 지정

→ rcParams 객체의 scatter.marker 속성에 지정된 기본값을 무시하고 매개변수에 지정된 값 사용

 

marker 매개변수를 '+'로 설정

plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1, marker='+')
plt.show()

 

여러 개의 서브플롯 출력하기

: 하나의 피겨 객체 안에는 여러 개의 서브플롯을 담을 수 있다.

서브플롯: 맷플롯립의 Axes 클래스의 객체

*하나의 서브플롯은 두 개 이상의 축 포함

*일반적으로 2차원 그래프의 수평축을 x축, 수직축을 y축으로 부른다.

*레이블: 축의 이름을 나타낸다.

 

  • 서브플롯 그리기: subplots() 함수

subplots() 함수로 두 개의 서브플롯을 그리고 싶다 → 매개변수에 2 넣어주기

→ 배열의 원소에서 각각 scatter() 함수와 hist() 함수 호출

*첫 번째 그래프인 산점도의 x축은 '도서권수'열이고 y축은 '대출건수'열이다.

*두 번째 그래프는 히스토그램으로 x축은 '대출건수'열이고 y축은 대출건수의 빈도에 해당한다.

*히스토그램의 y축은 로그 스케일로 지정

fig, axs = plt.subplots(2)

axs[0].scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)

axs[1].hist(ns_book7['대출건수'], bins=100)
axs[1].set_yscale('log')

fig.show()

*subplots() 함수는 피겨 객체와 각 서브플롯을 나타내는 Axes 객체의 배열을 반환

 

subplots() 함수도 피겨 크기를 지정할 수 있는 figsize 매개변수 제공

 

피겨 크기를 (6, 8)로 지정하여 높이 조절하고 set_title() 메서드를 사용해 제목 넣기

fig, axs = plt.subplots(2, figsize=(6, 8))

axs[0].scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
axs[0].set_title('scatter plot')

axs[1].hist(ns_book7['대출건수'], bins=100)
axs[1].set_title('histogram')
axs[1].set_yscale('log')

fig.show()

 

  • 서브플롯을 가로로 나란히 출력하기

: subplots() 함수에 행과 열을 지정하면 원하는 서브플롯 개수의 피겨를 만들 수 있다.

 

subplots(1, 2)와 같이 써서 하나의 행에 두 개의 열을 가진 피겨 만들기

: set_title() 메서드로 각 서브플롯의 이름을 지정하고 set_xlabel() 메서드와 set_ylabel() 메서드를 사용해 두 서브플롯의 축 이름 지정

fig, axs = plt.subplots(1, 2, figsize=(10, 4))

axs[0].scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
axs[0].set_title('scatter plot')
axs[0].set_xlabel('number of books')
axs[0].set_ylabel('borrow count')

axs[1].hist(ns_book7['대출건수'], bins=100)
axs[1].set_title('histogram')
axs[1].set_yscale('log')
axs[1].set_xlabel('borrow count')
axs[1].set_ylabel('frequency')

fig.show()

 

정리

함수/메서드 기능
matplotlib.pyplot.figure() 피겨 객체를 만들어 반환한다.
matplotlib.pyplot.subplots() 피겨와 서브플롯을 생성하여 반환한다.
Axes.set_xscale() 서브플롯의 x축 스케일을 지정한다.
Axes.set_yscale() 서브플롯의 y축 스케일을 지정한다.
Axes.set_title() 서브플롯의 제목을 설정한다.
Axes.set_xlabel() 서브플롯의 x축 이름을 지정한다.
Axes.set_ylabel() 서브플롯의 y축 이름을 지정한다.

05-2 선 그래프와 막대 그래프 그리기

 

선 그래프: 데이터 포인트 사이를 선으로 이은 그래프

막대 그래프: 데이터 포인트의 크기를 막대 높이로 나타내는 그래프

→ 한 축을 따라 어떤 데이터의 변화를 살펴보는데 용이하다.

 

연도별 발행 도서 개수 구하기

:ns_book7 데이터프레임에서 연도별 발행 도서 개수와 주제별 도서 개수 구하기

 

데이터 다시 다운

import gdown

gdown.download('https://bit.ly/3pK7iuu', 'ns_book7.csv', quiet=False)

 

판다스를 임포트한 후 데이터프레임으로 불러오기

import pandas as pd

ns_book7 = pd.read_csv('ns_book7.csv', low_memory=False)
ns_book7.head()

 

value_counts() 메서드: 데이터프레임의 한 열에서 이 메서드를 호출하면 고유한 값의 등장 횟수를 계산

'발행년도'열에서 value_counts() 메서드를 호출하여 반환된 결과 출력

count_by_year = ns_book7['발행년도'].value_counts()
count_by_year

*반환된 count_by_year는 판다스의 시리즈 객체

*첫 번째 열이 인덱스이고 두 번째 열이 값에 해당

 

연도를 시간순으로 배치하기 위해 sort_index() 메서드를 사용하여 인덱스 순서대로 데이터 정렬

count_by_year = count_by_year.sort_index()
count_by_year

 

count_by_year 객체에서 index 속성이 2030년보다 작거나 같은 데이터만 뽑기

count_by_year = count_by_year[count_by_year.index <= 2030]
count_by_year

 

주제별 도서 개수 구하기

: '주제분류번호'열에는 도서관에서 책을 분류하는 기준인 십진분류 코드가 기입되어 있다

→ '주제분류번호'열의 첫 번째 문자를 기준으로 도서 카운트하면 주제별 도서 개수를 구할 수 있다.

 

'주제분류번호'의 첫 번째 문자만 선택할 수 있다면 value_counts() 메서드를 적용

→ 이 열에는 NaN이 포함되어 있으므로 값이 NaN이라면 -1을 반환하는 함수를 만들어 걸러내야 한다.

'주제분류번호'열의 값을 받아 첫 번째 문자를 반환하는 kdc_1st_char() 함수를 선언한 후 apply() 메서드에 넣어 데이터프레임에 적용

import numpy as np

def kdc_1st_char(no):
    if no is np.nan:
        return '-1'
    else:
        return no[0]

count_by_subject = ns_book7['주제분류번호'].apply(kdc_1st_char).value_counts()
count_by_subject

 

선 그래프 그리기

: plot() 함수의 첫 번째 매개변수에는 x축의 값, 두 번째 매개변수에는 y축에 해당하는 값 전달

 

그래프 해상도를 높이기 위해 맷플롯립의 기본 DPI를 100으로 바꾸기

import matplotlib.pyplot as plt
plt.rcParams['figure.dpi'] = 100

 

plot() 함수의 두 매개변수에 count_by_year의 연도(index)와 도서 개수(values)을 각각 지정하여 선 그래프 그리기

: 서브플롯을 사용하지 않을 때는 그래프 제목은 title() 함수, x축 이름과 y축 이름은 각각 xlabel() 함수와 ylabel() 함수를 사용하여 지정

plt.plot(count_by_year.index, count_by_year.values)
plt.title('Books by year')
plt.xlabel('year')
plt.ylabel('number of books')
plt.show()

 

  • 선 모양과 색상 바꾸기

: plot() 함수는 linestyle 매개변수를 제공

*linestyle 매개변수 기본값은 실선을 나타내는 '-'이다.

이외에도

  • 실선 '-'
  • 점선 ':'
  • 쇄선 '-.'
  • 파선 '--'

*또한 color 매개변수에 색상을 지정할 수 있다.

 

마커는 점으로, 선은 점선을 사용한 선 그래프를 빨간색으로 그리기

: 시리즈 객체 그대로 plot() 함수에 전달 → 자동으로 인덱스를 x축의 좌표로 사용하여 그래프를 그린다.

plt.plot(count_by_year, marker='.', linestyle=':', color='red')
plt.title('Books by year')
plt.xlabel('year')
plt.ylabel('number of books')
plt.show()

*plot() 함수의 매개변수에 지정한 마커, 선 모양, 색깔을 하나의 문자열로 합쳐서 선 그래프의 포맷으로 나타낼 수 있다.

ply.plot(count_by_year, '.:r')

 

별 모양 마커와 실선을 사용한 선 그래프를 녹색으로 그리기

plt.plot(count_by_year, '*-g')
plt.title('Books by year')
plt.xlabel('year')
plt.ylabel('number of books')
plt.show()

 

  • 선 그래프 눈금 개수 조절 및 마커에 텍스트 표시하기

xticks() 함수: x축 눈금 지정

 

1947년부터 2030년까지 10년씩 건너뛰면서 x축의 눈금을 표시하기 위해 xticks() 함수 매개변수에 파이썬 range() 함수 사용

→ 슬라이스 연산자(:)를 사용해 5개씩 건너뛰면서 count_by_year의 값을 선택

*items() 메서드를 사용하면 인덱스와 값을 감싼 튜플을 얻을 수 있다.

 

annotate() 함수: 그래프에 값 표시

첫 번째 매개변수에 그래프에 나타낼 문자열을 지정하고, 두 번째 매개변수에 문자열이 나타날 x, y 좌표를 튜플로 지정

plt.plot(count_by_year, '*-g')
plt.title('Books by year')
plt.xlabel('year')
plt.ylabel('number of books')
plt.xticks(range(1947, 2030, 10))
for idx, val in count_by_year[::5].items():
    plt.annotate(val, (idx, val))
plt.show()

 

xtyest 매개변수: 텍스트 위치 조절

마커 위치에서 x축은 1만큼, y축은 10만큼 떨어지게 지정하기

plt.plot(count_by_year, '*-g')
plt.title('Books by year')
plt.xlabel('year')
plt.ylabel('number of books')
plt.xticks(range(1947, 2030, 10))
for idx, val in count_by_year[::5].items():
    plt.annotate(val, (idx, val), xytext=(idx+1, val+10))
plt.show()

 

textcoords 매개변수: 상대적인 위치를 포인트나 픽셀 단위로 지정

→ textcoords 매개변수에 포이느 단위의 상대 위치를 나타내는 'offset points'를 지정

plt.plot(count_by_year, '*-g')
plt.title('Books by year')
plt.xlabel('year')
plt.ylabel('number of books')
plt.xticks(range(1947, 2030, 10))
for idx, val in count_by_year[::5].items():
    plt.annotate(val, (idx, val), xytext=(2, 2), textcoords='offset points')
plt.show()

 

막대 그래프 그리기

: bar() 함수 사용

→ x축의 값과 막대 높이에 해당하는 y축의 값을 전달

 

annotate() 함수로 y축의 값을 표시할 때 텍스트 위치를 xytest=(0, 2)로 지정

plt.bar(count_by_subject.index, count_by_subject.values)
plt.title('Books by subject')
plt.xlabel('subject')
plt.ylabel('number of books')
for idx, val in count_by_subject.items():
    plt.annotate(val, (idx, val), xytext=(0, 2), textcoords='offset points')
plt.show()

 

  • 텍스트 정렬, 막대 조절 및 색상 바꾸기

텍스트 위치 조절: annotate() 함수의 ha 매개변수레 'center' 지정

택스트 크기 조절: fontsize 매개변수

텍스트 색깔: color 매개변수

막대 두께 조절: width 매개변수 (기본값 0.8)

 

plt.bar(count_by_subject.index, count_by_subject.values, width=0.7, color='blue')
plt.title('Books by subject')
plt.xlabel('subject')
plt.ylabel('number of books')
for idx, val in count_by_subject.items():
    plt.annotate(val, (idx, val), xytext=(0, 2), textcoords='offset points', 
                 fontsize=8, ha='center', color='green')
plt.show()

 

  • 가로 막대 그래프 그리기

: barh() 함수

막대 두께 나타내는 매개변수: height 매개변수

*x축과 y축의 이름 바꿔서 써야한다.

 

plt.barh(count_by_subject.index, count_by_subject.values, height=0.7, color='blue')
plt.title('Books by subject')
plt.xlabel('number of books')
plt.ylabel('subject')
for idx, val in count_by_subject.items():
    plt.annotate(val, (val, idx), xytext=(2, 0), textcoords='offset points', 
                 fontsize=8, va='center', color='green')
plt.show()

*가로 막대 그래프에서는 텍스트를 막대 중앙에 정렬할 때 va 매개변수 사용

*기본 값은 'baseline'으로 텍스트 밑면을 막대 중앙에 맞춘다.

*위로 정렬하는 'top'과 아래로 정렬하는 'bottom'

 

이미지 출력하고 저장하기

 

 

# 노트북이 코랩에서 실행 중인지 체크합니다.
import sys
if 'google.colab' in sys.modules:
    # 샘플 이미지를 다운로드합니다.
    !wget https://bit.ly/3wrj4xf -O jupiter.png

 

  • 이미지 읽기

: imread() 함수 → 파일 이름을 전달하면 이미지를 읽어 넘파이 배얼을 반환해준다.

img = plt.imread('jupiter.png')
img.shape

*반환된 배열의 크기 (이미지 높이, 너비, 채널) 의미

 

  • 이미지 화면에 출력하기

: imshow() 함수

plt.imshow(img)
plt.show()

*imshow() 함수는 피겨 크기에 상관없이 기본적으로 원본 이미지의 가로세로 비율 유지

 

축과 눈금을 표시하지 않으려면 axis() 함수를 'off'로 지정

plt.figure(figsize=(8, 6))
plt.imshow(img)
plt.axis('off')
plt.show()

 

  • 이미지 저장하기

: imsave() 함수 사용

*첫 번째 매개변수는 저장할 파일이름이고, 두 번째 매개변수는 이미지가 저장된 넘파이 배열

*파일 이름의 확장자를 사용해 자동으로 이미지를 변환해준다.

 

plt.imsave('jupiter.jpg', arr_img)

 

그래프를 이미지로 저장하기

: savefig() 함수 사용

*첫 번째 매개변수는 저장할 이미지의 파일 이름

*dpi 매개변수에는 그래프를 저장할 때 사용할 DPI를 따로 지정할 수 있다.

*rcParam['savefig.dpi']로 DPI를 지정할 수 있다.

*기본값은 'figure'로 피겨에서 설정한 DPI를 따른다.

 

plt.rcParams['savefig.dpi']

 

마지막에 그린 가로 막대 그래프를 savefig() 함수로 저장하기

*show() 함수가 호출되면 피겨 객체가 자동으로 소멸되므로 show() 함수 이전에 savefig() 를 호출해야 한다.

plt.barh(count_by_subject.index, count_by_subject.values, height=0.7, color='blue')
plt.title('Books by subject')
plt.xlabel('number of books')
plt.ylabel('subject')
for idx, val in count_by_subject.items():
    plt.annotate(val, (val, idx), xytext=(2, 0), textcoords='offset points', 
                 fontsize=8, va='center', color='green')
plt.savefig('books_by_subject.png')
plt.show()

 

저장된 파일 불러서 다시 출력

pil_img = Image.open('books_by_subject.png')

plt.figure(figsize=(8, 6))
plt.imshow(pil_img)
plt.axis('off')
plt.show()

 

정리

함수/메서드 기능
matplotlib.pyplot.plot() 선 그래프를 그린다.
matplotlib.pyplot.title() 그래프 제목을 설정한다.
matplotlib.pyplot.xlabel() x축 이름을 지정한다.
matplotlib.pyplot.ylabel() y축 이름을 지정한다.
matplotlib.pyplot.xticks() x축의 눈금 위치와 레이블을 지정한다.
matplotlib.pyplot.annotate() 지정한 좌표에 텍스트를 출력한다.
matplotlib.pyplot.bar() 세로 막대 그래프를 그린다.
matplotlib.pyplot.barh() 가로 막대 그래프를 그린다.
matplotlib.pyplot.imread() 이미지 파일을 넘파이 배열로 읽어들인다.
matplotlib.pyplot.imshow() 이미지를 출력한다.
matplotlib.pyplot.imsave() 넘파이 배열을 이미지 파일로 저장한다.
matplotlib.pyplot.savefig() 그래프를 이미지로 저장한다.

 

'혼자 공부하는 데이터 분석' 카테고리의 다른 글

7장 검증하고 예측하기  (0) 2023.06.11
6장 복잡한 데이터 표현하기  (0) 2023.06.08
4장 데이터 요약하기  (0) 2023.05.29
3장 데이터 정제하기  (0) 2023.05.22
2장 데이터 수집하기  (0) 2023.05.14

댓글