🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Matplotlib 시각화 심화 완벽 가이드 - 슬라이드 1/8
A

AI Generated

2025. 12. 16. · 7 Views

Matplotlib 시각화 심화 완벽 가이드

Python의 대표적인 시각화 라이브러리 Matplotlib의 심화 기능을 다룹니다. 선 그래프, 서브플롯, 범례, 스타일 설정 등 실무에서 자주 사용하는 고급 시각화 기법을 단계별로 학습합니다.


목차

  1. 선 그래프 (plt.plot) 그리기
  2. 여러 선 한 그래프에 표시
  3. 서브플롯 (subplot) 만들기
  4. figure와 axes 이해하기
  5. 범례 (legend) 추가
  6. 그리드와 스타일 설정
  7. 그래프 저장 옵션

1. 선 그래프 (plt.plot) 그리기

신입 데이터 분석가 김개발 씨는 월별 매출 데이터를 시각화하라는 첫 업무를 받았습니다. 엑셀로는 쉽게 할 수 있는데, Python으로는 어떻게 해야 할까요?

선배 박시니어 씨가 말합니다. "Matplotlib의 plot 함수만 알면 됩니다."

plt.plot은 Matplotlib의 가장 기본이 되는 함수로, 데이터를 선 그래프로 표현합니다. X축과 Y축 데이터를 전달하면 자동으로 점들을 연결하여 선을 그려줍니다.

색상, 선 스타일, 마커 등 다양한 옵션을 통해 그래프를 원하는 대로 꾸밀 수 있습니다.

다음 코드를 살펴봅시다.

import matplotlib.pyplot as plt

# 월별 매출 데이터 (단위: 백만원)
months = [1, 2, 3, 4, 5, 6]
sales = [120, 135, 148, 162, 155, 178]

# 선 그래프 그리기
plt.plot(months, sales, color='blue', linewidth=2, marker='o')

# 그래프 제목과 축 레이블 설정
plt.title('2024 Monthly Sales')
plt.xlabel('Month')
plt.ylabel('Sales (Million KRW)')

# 화면에 표시
plt.show()

김개발 씨는 입사 첫 주를 맞이한 데이터 분석가입니다. 팀장님으로부터 상반기 매출 데이터를 시각화하라는 업무를 받았습니다.

"엑셀이었으면 클릭 몇 번이면 되는데..." 하지만 회사에서는 모든 분석을 Python으로 진행합니다. 막막해하던 김개발 씨를 본 박시니어 씨가 다가왔습니다.

"Matplotlib의 plot 함수만 알면 쉬워요." 선 그래프란 무엇일까요? 마치 체온계의 수은주가 시간에 따라 올라가는 모습을 그래프로 그린 것과 같습니다. 점과 점을 선으로 연결하여 데이터의 변화 추이를 한눈에 볼 수 있게 만드는 것입니다.

매출 추이, 주가 변동, 기온 변화처럼 시간에 따른 변화를 표현할 때 가장 효과적입니다. 왜 엑셀 대신 Python을 사용할까요? 엑셀도 훌륭한 도구이지만 한계가 있습니다.

데이터가 수백만 건이 되면 느려지고, 같은 작업을 반복할 때마다 수동으로 클릭해야 합니다. 또한 여러 데이터 소스를 결합하거나 복잡한 전처리를 하기엔 불편합니다.

반면 Python은 한 번 코드를 작성하면 같은 작업을 자동화할 수 있습니다. 데이터베이스에서 직접 데이터를 가져오고, 전처리하고, 시각화까지 하나의 흐름으로 처리할 수 있습니다.

Matplotlib이 해결해주는 것 Matplotlib은 Python에서 가장 널리 사용되는 시각화 라이브러리입니다. plt.plot 함수 하나만으로도 전문가 수준의 그래프를 그릴 수 있습니다.

색상을 바꾸고, 선을 굵게 만들고, 점을 표시하는 것도 모두 파라미터 몇 개로 해결됩니다. 코드를 한 줄씩 살펴볼까요? 먼저 matplotlib.pyplot을 plt라는 이름으로 불러옵니다.

이것은 관례적으로 사용하는 방식입니다. 그다음 months와 sales라는 두 개의 리스트를 준비합니다.

하나는 X축(월), 하나는 Y축(매출) 데이터입니다. 핵심은 plt.plot(months, sales) 이 한 줄입니다.

이 코드만으로도 기본적인 선 그래프가 그려집니다. 하지만 여기에 **color='blue'**를 추가하면 파란색 선이 되고, linewidth=2를 넣으면 선이 두껍게 표시됩니다.

**marker='o'**는 각 데이터 포인트에 동그란 점을 찍어줍니다. plt.title은 그래프 상단에 제목을 달아줍니다.

plt.xlabelplt.ylabel은 각 축이 무엇을 의미하는지 명시합니다. 마지막으로 **plt.show()**를 호출하면 그래프가 화면에 나타납니다.

실무에서는 어떻게 활용할까요? 김개발 씨가 속한 팀에서는 매주 월요일마다 주간 리포트를 작성합니다. 데이터베이스에서 최신 매출 데이터를 가져와 자동으로 그래프를 생성하고, 이를 보고서에 첨부합니다.

코드 한 번 실행으로 모든 과정이 완료되니 시간을 크게 절약할 수 있습니다. 또한 여러 지점의 매출을 비교하거나, 전년 대비 증감률을 표시하는 등 복잡한 시각화도 가능합니다.

엑셀에서는 일일이 손으로 해야 했던 작업들이 코드 몇 줄로 해결됩니다. 초보자들이 자주 하는 실수 가장 흔한 실수는 **plt.show()**를 빼먹는 것입니다.

코드는 정상적으로 실행되지만 그래프가 화면에 나타나지 않아 당황하게 됩니다. Jupyter Notebook에서는 생략해도 자동으로 보이지만, 일반 Python 스크립트에서는 반드시 필요합니다.

또 다른 실수는 X축과 Y축의 데이터 개수가 다른 경우입니다. months가 6개인데 sales가 5개라면 에러가 발생합니다.

두 리스트의 길이는 항상 같아야 합니다. 다시 김개발 씨의 이야기로 박시니어 씨의 설명을 들은 김개발 씨는 직접 코드를 작성해보았습니다.

몇 번의 시행착오 끝에 멋진 매출 그래프가 화면에 나타났습니다. "생각보다 간단하네요!" plt.plot의 기본만 익혀도 대부분의 선 그래프를 그릴 수 있습니다.

데이터 분석의 첫걸음은 데이터를 눈으로 보는 것입니다. 오늘 배운 내용을 실제 데이터에 적용해보세요.

실전 팁

💡 - plt.show() 대신 plt.savefig('graph.png')로 파일로 저장할 수 있습니다

  • marker 옵션은 'o', 's', '^', '*' 등 다양한 모양을 지원합니다

2. 여러 선 한 그래프에 표시

김개발 씨는 이번에는 서울과 부산 두 지점의 매출을 비교하라는 업무를 받았습니다. 두 개의 그래프를 따로 그려야 할까요?

박시니어 씨가 웃으며 말합니다. "plt.plot을 여러 번 호출하면 됩니다."

하나의 그래프에 여러 개의 선을 그리려면 plt.plot을 여러 번 호출하면 됩니다. 각각 다른 색상과 스타일을 지정하여 구분할 수 있습니다.

plt.legend를 추가하면 어떤 선이 무엇을 나타내는지 범례로 표시할 수 있습니다.

다음 코드를 살펴봅시다.

import matplotlib.pyplot as plt

# 월별 데이터
months = [1, 2, 3, 4, 5, 6]
seoul_sales = [120, 135, 148, 162, 155, 178]
busan_sales = [95, 102, 118, 125, 130, 145]

# 서울 지점 매출 (파란색)
plt.plot(months, seoul_sales, color='blue', linewidth=2,
         marker='o', label='Seoul')

# 부산 지점 매출 (빨간색)
plt.plot(months, busan_sales, color='red', linewidth=2,
         marker='s', label='Busan')

# 범례 표시
plt.legend()
plt.title('Regional Sales Comparison')
plt.xlabel('Month')
plt.ylabel('Sales (Million KRW)')
plt.show()

김개발 씨는 이제 기본적인 선 그래프를 그릴 수 있게 되었습니다. 그런데 새로운 요청이 들어왔습니다.

서울과 부산 두 지점의 매출을 비교하는 그래프를 만들어달라는 것입니다. "두 개의 그래프를 따로 그려야 하나?" 고민하던 김개발 씨에게 박시니어 씨가 힌트를 줍니다.

"하나의 그래프에 여러 선을 그리면 비교가 훨씬 쉬워요." 비교를 위한 시각화 마치 육상 경기에서 두 선수가 나란히 달리는 모습을 상상해보세요. 각자 따로 달리는 것을 보는 것보다, 나란히 달리는 모습을 보면 누가 빠른지 한눈에 알 수 있습니다.

그래프도 마찬가지입니다. 같은 축을 공유하면 비교가 쉬워집니다.

하나의 캔버스에 여러 그림 Matplotlib은 똑똑합니다. plt.plot을 여러 번 호출하면 같은 그래프 위에 계속 선을 추가합니다.

첫 번째 plot은 파란색으로, 두 번째 plot은 빨간색으로 지정하면 두 선이 한 화면에 나타납니다. 색상만으로는 부족합니다 색맹이 있는 사람도 있고, 흑백 프린터로 출력할 수도 있습니다.

그래서 색상뿐 아니라 마커 모양도 다르게 하는 것이 좋습니다. 서울은 동그라미(o), 부산은 네모(s)처럼 구분하면 더 명확합니다.

범례의 중요성 파란 선과 빨간 선이 있는데, 어느 것이 서울이고 어느 것이 부산일까요? 그래프를 보는 사람은 알 수 없습니다.

바로 이럴 때 **plt.legend()**가 필요합니다. 각 plot에 **label='Seoul'**처럼 이름을 붙이고, legend를 호출하면 자동으로 범례가 생성됩니다.

코드 분석 먼저 두 개의 데이터 리스트를 준비합니다. seoul_sales와 busan_sales입니다.

첫 번째 plt.plot에서는 서울 데이터를 파란색 선으로 그립니다. 이때 **label='Seoul'**을 꼭 넣어야 합니다.

두 번째 plt.plot에서는 부산 데이터를 빨간색 선으로 그립니다. 마커 모양을 's'(네모)로 바꿔서 서울과 구분합니다.

마지막으로 **plt.legend()**를 호출하면 오른쪽 상단에 범례가 나타납니다. 실무에서의 활용 김개발 씨가 속한 회사는 전국에 20개 지점이 있습니다.

매달 모든 지점의 매출을 비교해야 합니다. 이때 주요 3~4개 지점만 선 그래프로 표시하면 전체 트렌드를 파악하기 쉽습니다.

예를 들어 서울, 부산, 대구, 광주의 매출을 한 그래프에 그리면 어느 지역이 성장세인지, 어느 지역이 정체되었는지 한눈에 보입니다. 경영진은 이런 그래프를 매우 좋아합니다.

너무 많은 선은 독이 됩니다 하지만 주의할 점이 있습니다. 선이 너무 많으면 오히려 알아보기 어렵습니다.

20개 지점을 모두 한 그래프에 그리면 선들이 뒤엉켜서 혼란스럽습니다. 보통 4~5개 이하로 제한하는 것이 좋습니다.

더 많은 데이터를 표시해야 한다면 다른 방법을 고려해야 합니다. 예를 들어 서브플롯을 사용하거나, 중요한 몇 개만 강조하고 나머지는 연한 색으로 배경처럼 표시하는 방법도 있습니다.

다시 김개발 씨의 이야기로 김개발 씨는 서울과 부산의 매출 비교 그래프를 완성했습니다. 팀장님께 보고하자 "이거면 한눈에 보이네요!"라는 칭찬을 받았습니다.

간단한 기법 하나가 보고서의 품질을 크게 높였습니다. 여러 데이터를 비교할 때는 하나의 그래프에 표시하는 것을 고려해보세요.

비교가 쉬워지고 인사이트를 발견하기도 쉬워집니다.

실전 팁

💡 - plt.legend(loc='upper left')로 범례 위치를 지정할 수 있습니다

  • 선이 너무 많으면 alpha=0.5로 투명도를 조절하여 겹침을 방지하세요

3. 서브플롯 (subplot) 만들기

이번에는 매출, 비용, 이익을 각각 별도 그래프로 표시해야 합니다. 세 개의 그래프를 하나씩 그려서 저장해야 할까요?

박시니어 씨가 말합니다. "subplot을 사용하면 한 화면에 여러 그래프를 배치할 수 있어요."

subplot은 하나의 figure(그림판) 안에 여러 개의 그래프를 격자 형태로 배치하는 기능입니다. plt.subplot(행, 열, 인덱스) 형식으로 사용하며, 각 위치에 독립적인 그래프를 그릴 수 있습니다.

여러 관련된 데이터를 한눈에 비교할 때 매우 유용합니다.

다음 코드를 살펴봅시다.

import matplotlib.pyplot as plt

months = [1, 2, 3, 4, 5, 6]
sales = [120, 135, 148, 162, 155, 178]
costs = [80, 85, 90, 95, 92, 98]
profit = [40, 50, 58, 67, 63, 80]

# 1행 3열 구조에서 첫 번째 위치
plt.subplot(1, 3, 1)
plt.plot(months, sales, 'b-o')
plt.title('Sales')

# 1행 3열 구조에서 두 번째 위치
plt.subplot(1, 3, 2)
plt.plot(months, costs, 'r-s')
plt.title('Costs')

# 1행 3열 구조에서 세 번째 위치
plt.subplot(1, 3, 3)
plt.plot(months, profit, 'g-^')
plt.title('Profit')

plt.tight_layout()  # 레이아웃 자동 조정
plt.show()

김개발 씨의 실력이 점점 늘자 업무도 복잡해졌습니다. 이번에는 월별 매출, 비용, 이익을 모두 시각화하라는 요청입니다.

"세 개의 파일로 따로 저장해야 하나?" 고민하던 김개발 씨에게 박시니어 씨가 새로운 기법을 알려줍니다. "subplot을 사용하면 한 화면에 여러 그래프를 깔끔하게 배치할 수 있어요." 아파트 평면도를 상상해보세요 subplot은 마치 아파트 평면도를 나누는 것과 같습니다.

큰 거실 공간을 방 3개로 나누듯이, 하나의 큰 그림판을 여러 개의 작은 그래프 공간으로 나눕니다. 각 방마다 다른 가구를 배치하듯, 각 subplot에는 다른 그래프를 그릴 수 있습니다.

왜 subplot이 필요할까요? 관련된 여러 데이터를 분석할 때 각각 따로 보는 것보다 나란히 보는 것이 훨씬 효과적입니다. 매출이 올랐는데 이익은 왜 안 올랐을까?

이런 질문에 답하려면 매출과 이익을 동시에 봐야 합니다. 하나씩 파일을 열어보는 것은 비효율적입니다.

창을 왔다 갔다 하면서 비교하기도 어렵습니다. subplot을 사용하면 모든 정보가 한 화면에 있어서 비교가 쉽습니다.

subplot의 좌표 시스템 **plt.subplot(1, 3, 1)**에서 숫자들이 의미하는 것을 알아볼까요? 첫 번째 숫자는 행의 개수, 두 번째는 열의 개수입니다.

(1, 3)이면 1행 3열, 즉 가로로 3개를 나란히 배치한다는 뜻입니다. 세 번째 숫자는 인덱스입니다.

왼쪽 위부터 1번으로 시작하여 오른쪽으로 갑니다. (2, 2) 구조라면 1번은 왼쪽 위, 2번은 오른쪽 위, 3번은 왼쪽 아래, 4번은 오른쪽 아래입니다.

코드를 단계별로 살펴보기 먼저 세 가지 데이터를 준비합니다. sales, costs, profit입니다.

첫 번째 plt.subplot(1, 3, 1)을 호출하면 1행 3열 구조의 첫 번째 칸이 활성화됩니다. 이제 plt.plot을 호출하면 그 칸에 그래프가 그려집니다.

두 번째 plt.subplot(1, 3, 2)를 호출하면 두 번째 칸으로 이동합니다. 여기에 비용 그래프를 그립니다.

세 번째 칸도 같은 방식입니다. 각 그래프마다 plt.title로 제목을 붙여서 무엇을 나타내는지 명확히 합니다.

tight_layout의 마법 subplot을 사용하다 보면 그래프들이 너무 붙어서 제목이나 레이블이 겹치는 경우가 있습니다. **plt.tight_layout()**은 이런 문제를 자동으로 해결해줍니다.

각 subplot 사이의 간격을 적절히 조정하여 깔끔하게 배치합니다. 실무 활용 사례 김개발 씨의 팀에서는 주간 보고서에 항상 4개의 그래프를 포함합니다.

매출, 비용, 이익, 그리고 고객 수입니다. subplot(2, 2)로 2행 2열 구조를 만들어서 네 개를 한 화면에 표시합니다.

경영진은 이 한 장의 그래프만 봐도 전체 상황을 파악할 수 있습니다. "이번 주는 매출은 올랐지만 고객 수는 줄었네요"처럼 즉각적인 인사이트를 얻을 수 있습니다.

흔한 실수 초보자들이 자주 하는 실수는 subplot을 호출할 때마다 새로운 figure가 생긴다고 생각하는 것입니다. 실제로는 하나의 figure 안에서 현재 활성화된 subplot만 바뀝니다.

모든 subplot 호출 후 마지막에 plt.show()를 한 번만 호출하면 됩니다. 또 다른 실수는 인덱스를 0부터 시작한다고 생각하는 것입니다.

Python의 리스트는 0부터 시작하지만, subplot의 인덱스는 1부터 시작합니다. plt.subplot(2, 2, 0)은 에러입니다.

정리하며 김개발 씨는 subplot 기능을 익히고 나서 보고서 작성 시간이 크게 줄었습니다. 여러 파일을 관리할 필요도 없고, 한눈에 비교할 수 있어서 분석도 빨라졌습니다.

관련된 여러 데이터를 시각화할 때는 subplot을 적극 활용해보세요. 정보 전달력이 훨씬 높아집니다.

실전 팁

💡 - plt.subplots(2, 2)를 사용하면 fig, axes 객체를 한 번에 생성할 수 있어 더 편리합니다

  • figsize=(12, 4)로 전체 figure 크기를 조정할 수 있습니다

4. figure와 axes 이해하기

박시니어 씨가 김개발 씨의 코드를 보다가 물었습니다. "subplot 말고 더 유연한 방법도 있어요.

figure와 axes 객체를 직접 다루는 방법이죠." 김개발 씨는 지금까지 plt.plot만 써왔는데, 무슨 말일까요?

figure는 전체 그림판이고, axes는 그 안에 그려지는 개별 그래프 영역입니다. plt.subplots()로 figure와 axes 객체를 명시적으로 생성하면 더 세밀한 제어가 가능합니다.

이 방식은 복잡한 레이아웃이나 고급 커스터마이징이 필요할 때 필수적입니다.

다음 코드를 살펴봅시다.

import matplotlib.pyplot as plt
import numpy as np

# figure와 axes 객체 생성 (2행 2열)
fig, axes = plt.subplots(2, 2, figsize=(10, 8))

# 데이터 준비
x = np.linspace(0, 10, 100)

# 각 axes에 접근하여 그래프 그리기
axes[0, 0].plot(x, np.sin(x))
axes[0, 0].set_title('Sine Wave')

axes[0, 1].plot(x, np.cos(x), 'r')
axes[0, 1].set_title('Cosine Wave')

axes[1, 0].plot(x, x**2, 'g')
axes[1, 0].set_title('Quadratic')

axes[1, 1].plot(x, np.exp(x/10), 'm')
axes[1, 1].set_title('Exponential')

# 전체 제목 설정
fig.suptitle('Mathematical Functions', fontsize=16)
plt.tight_layout()
plt.show()

김개발 씨는 이제 제법 능숙하게 그래프를 그릴 수 있게 되었습니다. 그런데 박시니어 씨가 코드 리뷰를 하다가 말합니다.

"지금까지는 plt.plot, plt.subplot처럼 함수 위주로 작성했죠? 이제 객체 지향 방식을 배워볼까요?" "객체 지향 방식이요?" 김개발 씨는 고개를 갸우뚱했습니다.

캔버스와 그림의 관계 화가가 그림을 그리는 과정을 상상해보세요. 먼저 큰 캔버스를 준비합니다.

그다음 그 캔버스 위에 여러 개의 그림을 그립니다. Matplotlib도 똑같습니다.

figure가 캔버스이고, axes가 그 위에 그려지는 각각의 그림입니다. 지금까지 사용한 plt.plot()은 자동으로 figure와 axes를 생성해주는 편리한 방식이었습니다.

하지만 더 복잡한 작업을 하려면 이 객체들을 직접 다룰 줄 알아야 합니다. 왜 객체를 직접 다뤄야 할까요? 함수 방식(plt.plot)은 간단한 그래프에는 충분합니다.

하지만 각 subplot마다 다른 설정을 적용하거나, 특정 그래프만 수정하거나, 복잡한 레이아웃을 만들려면 한계가 있습니다. 객체 지향 방식을 사용하면 각 axes를 변수에 저장하여 언제든 접근할 수 있습니다.

"첫 번째 그래프의 배경색만 바꾸고 싶어"라는 요구사항도 쉽게 해결됩니다. plt.subplots의 마법 **fig, axes = plt.subplots(2, 2)**는 무엇을 반환할까요?

fig는 전체 figure 객체이고, axes는 2x2 크기의 배열입니다. 이 배열의 각 요소가 하나의 axes 객체입니다.

**axes[0, 0]**은 첫 번째 행, 첫 번째 열의 그래프를 의미합니다. 이 객체에 대고 **axes[0, 0].plot()**을 호출하면 그 위치에 그래프가 그려집니다.

plt.plot이 아니라 axes.plot이라는 점에 주목하세요. 코드 분석 먼저 numpy로 0부터 10까지 100개의 점을 생성합니다.

그다음 plt.subplots(2, 2, figsize=(10, 8))로 2행 2열의 subplot 구조를 만듭니다. figsize는 전체 figure의 크기를 인치 단위로 지정합니다.

이제 axes 배열을 인덱싱하여 각 위치에 접근합니다. **axes[0, 0]**은 왼쪽 위 그래프입니다.

여기에 사인 함수를 그립니다. set_title은 plt.title과 같은 역할이지만 특정 axes에만 적용됩니다.

같은 방식으로 코사인, 이차함수, 지수함수를 각 위치에 그립니다. 마지막으로 fig.suptitle로 전체 figure에 대한 제목을 붙입니다.

이것은 각 subplot의 제목보다 상위 레벨입니다. 실무에서의 활용 김개발 씨의 팀에서는 A/B 테스트 결과를 시각화할 때 이 방식을 사용합니다.

각 실험 그룹마다 여러 지표를 표시해야 하는데, 특정 그룹의 특정 지표만 강조하고 싶을 때가 있습니다. 객체 지향 방식을 사용하면 **axes[1, 2].set_facecolor('yellow')**처럼 특정 그래프의 배경색만 바꿀 수 있습니다.

또는 **axes[0, 0].grid(True)**로 첫 번째 그래프에만 격자를 추가할 수도 있습니다. 함수 방식 vs 객체 지향 방식 plt.plot()과 axes.plot()은 거의 같은 기능을 합니다.

차이는 제어의 정밀도입니다. 함수 방식은 "현재 활성화된" axes에 작업을 합니다.

객체 지향 방식은 원하는 axes를 정확히 지정합니다. 간단한 그래프라면 함수 방식이 더 편합니다.

하지만 subplot이 4개 이상이거나, 나중에 특정 그래프를 수정해야 한다면 객체 지향 방식이 훨씬 낫습니다. 흔한 실수 subplot이 하나뿐인 경우(1, 1) axes는 배열이 아니라 단일 객체입니다.

**axes[0, 0]**로 접근하면 에러가 납니다. 이럴 때는 그냥 **axes.plot()**을 사용해야 합니다.

또는 plt.subplots의 squeeze 파라미터를 False로 설정하면 항상 배열로 반환됩니다. 정리하며 박시니어 씨의 설명을 듣고 김개발 씨는 "아, 그래서 figure와 axes가 따로 있었구나!"하고 이해했습니다.

처음에는 복잡해 보였지만, 익숙해지니 오히려 더 직관적이었습니다. 복잡한 시각화를 만들 때는 객체 지향 방식을 사용해보세요.

코드가 더 명확해지고 유지보수도 쉬워집니다.

실전 팁

💡 - fig.savefig('output.png', dpi=300)으로 고해상도 이미지를 저장할 수 있습니다

  • axes.flatten()을 사용하면 2D 배열을 1D로 펼쳐서 반복문으로 쉽게 접근할 수 있습니다

5. 범례 (legend) 추가

김개발 씨가 만든 그래프를 보던 팀장님이 물었습니다. "이 파란 선이 뭐고 빨간 선이 뭐죠?" 범례를 깜빡한 것입니다.

박시니어 씨가 조언합니다. "범례는 선택이 아니라 필수예요."

**범례(legend)**는 그래프의 각 요소가 무엇을 나타내는지 설명하는 작은 상자입니다. plot 함수에 label 파라미터를 추가하고 **plt.legend()**를 호출하면 자동으로 생성됩니다.

위치, 폰트 크기, 테두리 스타일 등 다양한 옵션으로 커스터마이징할 수 있습니다.

다음 코드를 살펴봅시다.

import matplotlib.pyplot as plt

months = [1, 2, 3, 4, 5, 6]
product_a = [120, 135, 148, 162, 155, 178]
product_b = [95, 102, 118, 125, 130, 145]
product_c = [80, 88, 92, 98, 95, 102]

# 각 제품 매출 그래프 (label 지정)
plt.plot(months, product_a, 'b-o', linewidth=2, label='Product A')
plt.plot(months, product_b, 'r-s', linewidth=2, label='Product B')
plt.plot(months, product_c, 'g-^', linewidth=2, label='Product C')

# 범례 추가 (위치, 폰트 크기, 프레임 설정)
plt.legend(loc='upper left', fontsize=10, frameon=True, shadow=True)

plt.title('Product Sales Comparison')
plt.xlabel('Month')
plt.ylabel('Sales (Million KRW)')
plt.grid(True, alpha=0.3)
plt.show()

김개발 씨는 세 가지 제품의 매출을 비교하는 멋진 그래프를 만들었습니다. 색깔도 다르고 마커도 다르게 해서 구분이 잘 됩니다.

자신만만하게 팀장님께 보고했는데 예상치 못한 질문을 받았습니다. "이 파란 선이 어떤 제품이죠?" 김개발 씨는 당황했습니다.

범례를 넣지 않았던 것입니다. 지도 없이 여행하기 범례 없는 그래프는 마치 범례 없는 지도와 같습니다.

색깔과 기호가 가득하지만 무엇을 의미하는지 알 수 없습니다. 빨간 선, 파란 선, 초록 선이 있어도 어느 것이 무엇인지 설명이 없으면 소용없습니다.

특히 그래프를 처음 보는 사람은 더 혼란스럽습니다. 만든 사람은 "파란색이 A 제품이지"라고 당연히 알지만, 보는 사람은 추측할 수밖에 없습니다.

범례는 필수입니다 프로페셔널한 데이터 시각화에서 범례는 선택이 아니라 필수입니다. 논문, 보고서, 프레젠테이션 어디에서든 범례가 없는 그래프는 미완성으로 간주됩니다.

Matplotlib은 범례를 매우 쉽게 만들 수 있습니다. 두 가지만 하면 됩니다.

첫째, plot 함수에 **label='이름'**을 추가합니다. 둘째, **plt.legend()**를 호출합니다.

끝입니다. label의 역할 **plt.plot(x, y, label='Product A')**에서 label은 이 선의 이름을 지정합니다.

이 정보는 나중에 plt.legend()가 호출될 때 사용됩니다. label을 지정하지 않으면 범례에 나타나지 않습니다.

여러 개의 plot이 있다면 각각에 다른 label을 붙여야 합니다. 같은 이름을 사용하면 범례에서 하나로 합쳐집니다.

범례의 위치 조정 **plt.legend(loc='upper left')**에서 loc 파라미터는 범례의 위치를 지정합니다. 'upper left'는 왼쪽 위, 'upper right'는 오른쪽 위, 'lower left'는 왼쪽 아래입니다.

'best'를 사용하면 Matplotlib이 자동으로 최적의 위치를 찾아줍니다. 그래프의 데이터가 주로 아래쪽에 있다면 범례를 위쪽에 두는 것이 좋습니다.

반대로 데이터가 위쪽에 몰려있다면 범례를 아래쪽에 두면 겹치지 않습니다. 코드 분석 세 개의 제품 데이터를 준비합니다.

각 plt.plot 호출 시 **label='Product A'**처럼 이름을 붙입니다. 이 이름이 나중에 범례에 표시됩니다.

**plt.legend(loc='upper left', fontsize=10, frameon=True, shadow=True)**를 보면 여러 옵션이 있습니다. fontsize는 범례 글자 크기, frameon은 테두리 표시 여부, shadow는 그림자 효과입니다.

이런 옵션들로 범례를 더 예쁘게 꾸밀 수 있습니다. 실무 활용 김개발 씨의 회사에서는 경쟁사와의 시장 점유율을 비교하는 그래프를 만듭니다.

우리 회사, 경쟁사 A, 경쟁사 B, 경쟁사 C를 모두 표시해야 합니다. 범례가 없으면 어느 선이 우리 회사인지 알 수 없습니다.

또한 색상만으로 구분하면 색맹인 사람은 구분하기 어렵습니다. 범례에 선 스타일과 마커도 함께 표시되므로 색상 외에도 구분할 수 있는 정보를 제공합니다.

범례가 데이터를 가릴 때 때로는 범례가 그래프의 중요한 부분을 가리는 경우가 있습니다. 이럴 때는 bbox_to_anchor 파라미터를 사용하여 범례를 그래프 바깥쪽에 배치할 수 있습니다.

예를 들어 **plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')**는 범례를 그래프 오른쪽 바깥에 배치합니다. 이렇게 하면 데이터와 겹치지 않습니다.

흔한 실수 label을 지정했는데 범례가 안 나타난다면 plt.legend()를 호출했는지 확인하세요. label만 있고 legend 호출이 없으면 범례는 생성되지 않습니다.

반대로 legend를 호출했는데 비어있다면 어떤 plot에도 label을 지정하지 않은 것입니다. 최소한 하나의 plot에는 label이 있어야 합니다.

정리하며 김개발 씨는 범례를 추가한 그래프를 다시 팀장님께 보여드렸습니다. "이제 한눈에 보이네요!"라는 칭찬을 들었습니다.

작은 요소 하나가 그래프의 완성도를 크게 높였습니다. 그래프를 만들 때는 항상 범례를 추가하는 습관을 들이세요.

보는 사람에 대한 배려이자 프로페셔널의 기본입니다.

실전 팁

💡 - ncol=2로 범례를 2열로 표시하여 공간을 절약할 수 있습니다

  • title='Category'로 범례에 제목을 붙일 수 있습니다

6. 그리드와 스타일 설정

김개발 씨의 그래프를 본 디자이너가 말했습니다. "기능은 완벽한데 좀 더 세련되게 만들 수 없을까요?" 박시니어 씨가 웃으며 말합니다.

"그리드와 스타일만 잘 써도 훨씬 전문적으로 보입니다."

**그리드(grid)**는 그래프에 격자선을 추가하여 값을 읽기 쉽게 만듭니다. **plt.style.use()**로 Matplotlib의 사전 정의된 스타일을 적용할 수 있습니다.

색상, 선 스타일, 배경색 등을 일관되게 설정하여 전문적인 느낌을 줄 수 있습니다.

다음 코드를 살펴봅시다.

import matplotlib.pyplot as plt

# 스타일 적용 (ggplot 스타일)
plt.style.use('seaborn-v0_8-darkgrid')

months = [1, 2, 3, 4, 5, 6]
sales = [120, 135, 148, 162, 155, 178]

# 그래프 생성
plt.figure(figsize=(10, 6))
plt.plot(months, sales, linewidth=3, marker='o',
         markersize=8, color='#2E86AB', label='Sales')

# 그리드 설정 (투명도와 스타일 조정)
plt.grid(True, linestyle='--', alpha=0.5, linewidth=0.7)

plt.title('Monthly Sales Report', fontsize=16, fontweight='bold', pad=20)
plt.xlabel('Month', fontsize=12)
plt.ylabel('Sales (Million KRW)', fontsize=12)
plt.legend(fontsize=11)

# 축 범위 설정
plt.ylim(100, 190)

plt.tight_layout()
plt.show()

김개발 씨의 그래프는 기능적으로는 완벽했습니다. 데이터도 정확하고 범례도 있습니다.

하지만 회사 디자이너가 보더니 "뭔가 심심하네요"라고 말했습니다. 어떻게 하면 더 세련되게 만들 수 있을까요?

박시니어 씨가 힌트를 줍니다. "그리드와 스타일만 잘 활용해도 확 달라 보입니다." 그리드의 힘 그래프를 볼 때 "이 점의 정확한 값이 뭐지?"라고 궁금할 때가 있습니다.

격자선이 있으면 대략적인 값을 쉽게 읽을 수 있습니다. 마치 공책의 모눈종이처럼 기준선이 있으면 위치를 파악하기 쉬운 것과 같습니다.

**plt.grid(True)**만 호출해도 기본 격자선이 그려집니다. 하지만 기본 설정은 너무 진하거나 눈에 거슬릴 수 있습니다.

그래서 투명도와 선 스타일을 조정하는 것이 중요합니다. 그리드 커스터마이징 **plt.grid(True, linestyle='--', alpha=0.5)**에서 각 파라미터를 살펴볼까요?

**linestyle='--'**는 점선으로 그리라는 뜻입니다. 실선보다 덜 거슬립니다.

alpha=0.5는 투명도를 50%로 설정하여 은은하게 보이게 합니다. linewidth=0.7로 선을 얇게 만들면 더 세련됩니다.

격자는 주인공이 아니라 조연입니다. 너무 튀면 안 됩니다.

스타일의 마법 Matplotlib은 여러 가지 사전 정의된 스타일을 제공합니다. **plt.style.use('seaborn-v0_8-darkgrid')**를 호출하면 전체 그래프의 느낌이 바뀝니다.

색상 팔레트, 배경색, 격자선 스타일 등이 일괄 변경됩니다. 다른 인기 있는 스타일로는 'ggplot'(R의 ggplot2 스타일), 'fivethirtyeight'(데이터 저널리즘 사이트 스타일), 'bmh'(Bayesian Methods for Hackers 스타일) 등이 있습니다.

각각 독특한 분위기를 가지고 있습니다. 색상 선택의 중요성 **color='#2E86AB'**처럼 HEX 코드를 사용하면 정확한 색상을 지정할 수 있습니다.

기본 색상(blue, red)보다 전문적으로 보입니다. 회사 브랜드 색상이 있다면 그것을 사용하는 것도 좋습니다.

색상은 너무 많으면 오히려 산만합니다. 보통 주요 색상 2~3개를 정하고 일관되게 사용하는 것이 좋습니다.

폰트 설정 fontsize=16, fontweight='bold', pad=20처럼 제목의 폰트를 크고 굵게 만들면 시선을 끕니다. pad=20은 제목과 그래프 사이의 간격을 조정합니다.

너무 붙어있으면 답답해 보입니다. 축 레이블도 적절한 크기로 설정해야 합니다.

너무 작으면 안 보이고, 너무 크면 부담스럽습니다. 보통 제목은 16pt, 레이블은 12pt 정도가 적당합니다.

코드 분석 먼저 스타일을 적용합니다. 이것은 figure를 만들기 전에 해야 합니다.

그다음 **plt.figure(figsize=(10, 6))**로 그래프 크기를 지정합니다. 기본 크기보다 조금 크게 만들면 여유로워 보입니다.

plot 함수에서 linewidth=3으로 선을 두껍게, markersize=8로 마커를 크게 만듭니다. 작은 그래프에서는 잘 안 보이므로 적절히 크기를 조정합니다.

**plt.ylim(100, 190)**은 Y축의 범위를 설정합니다. 데이터가 120178인데 축이 0200이면 변화가 작아 보입니다.

적절한 범위로 제한하면 변화가 더 명확히 보입니다. 실무 활용 김개발 씨의 팀에서는 회사 브랜드 색상을 사용한 커스텀 스타일을 만들었습니다.

모든 보고서에 일관된 스타일을 적용하니 훨씬 전문적으로 보입니다. 경영진도 "요즘 그래프가 깔끔해졌네요"라고 좋아합니다.

한 번 스타일을 정하면 계속 재사용할 수 있습니다. 매번 색상과 폰트를 고민할 필요 없이 일관된 품질을 유지할 수 있습니다.

과유불급 하지만 너무 화려하게 꾸미는 것은 역효과입니다. 그림자, 3D 효과, 화려한 색상을 남발하면 오히려 데이터가 묻힙니다.

시각화의 목적은 데이터를 명확히 전달하는 것입니다. 장식은 그것을 돕는 역할일 뿐입니다.

정리하며 디자이너의 피드백을 받은 김개발 씨는 그리드와 스타일을 적용한 그래프를 다시 만들었습니다. 같은 데이터인데 훨씬 세련되어 보입니다.

"이 정도면 프레젠테이션에 써도 되겠네요!" 그래프는 데이터만큼이나 디자인도 중요합니다. 좋은 스타일로 전문성을 높여보세요.

실전 팁

💡 - plt.style.available로 사용 가능한 모든 스타일을 확인할 수 있습니다

  • plt.rcParams['font.family'] = 'Arial'로 폰트를 전역적으로 변경할 수 있습니다

7. 그래프 저장 옵션

김개발 씨가 만든 멋진 그래프를 보고서에 넣으려고 하는데, 이미지 품질이 떨어져 보입니다. 박시니어 씨가 말합니다.

"plt.savefig의 옵션을 제대로 사용해야 고품질 이미지를 얻을 수 있어요."

**plt.savefig()**는 그래프를 이미지 파일로 저장하는 함수입니다. DPI(해상도), 포맷(PNG, PDF, SVG), 배경색, 여백 등 다양한 옵션을 제공합니다.

적절한 설정으로 출판 품질의 이미지를 만들 수 있습니다.

다음 코드를 살펴봅시다.

import matplotlib.pyplot as plt

months = [1, 2, 3, 4, 5, 6]
sales = [120, 135, 148, 162, 155, 178]

plt.figure(figsize=(10, 6))
plt.plot(months, sales, linewidth=2, marker='o', color='#2E86AB')
plt.title('Monthly Sales Report', fontsize=16, fontweight='bold')
plt.xlabel('Month', fontsize=12)
plt.ylabel('Sales (Million KRW)', fontsize=12)
plt.grid(True, linestyle='--', alpha=0.5)

# 다양한 저장 옵션
# 고해상도 PNG (300 DPI, 투명 배경)
plt.savefig('sales_report.png', dpi=300, bbox_inches='tight',
            transparent=True, facecolor='white')

# 벡터 포맷 (PDF) - 확대해도 깨지지 않음
plt.savefig('sales_report.pdf', bbox_inches='tight')

# SVG 포맷 (웹용, 일러스트레이터 편집 가능)
plt.savefig('sales_report.svg', bbox_inches='tight')

plt.show()

김개발 씨는 완벽한 그래프를 만들었습니다. 화면에서는 선명하고 아름답습니다.

그런데 이것을 파워포인트에 넣으니 뭔가 흐릿하고 품질이 떨어져 보입니다. 왜 그럴까요?

박시니어 씨가 설명합니다. "그래프를 저장할 때 옵션을 제대로 설정해야 합니다." 화면과 인쇄의 차이 화면용과 인쇄용 이미지는 필요한 해상도가 다릅니다.

웹이나 화면에서는 72~96 DPI면 충분하지만, 인쇄물이나 프레젠테이션에서는 300 DPI 이상이 필요합니다. DPI는 Dots Per Inch의 약자로, 1인치당 점의 개수를 의미합니다.

Matplotlib의 기본 DPI는 100입니다. 화면에서는 괜찮지만 확대하거나 인쇄하면 품질이 떨어집니다.

dpi=300으로 설정하면 출판 품질의 이미지를 얻을 수 있습니다. bbox_inches의 마법 그래프를 저장할 때 주변에 불필요한 여백이 많이 생기는 경우가 있습니다.

**bbox_inches='tight'**를 사용하면 실제 그래프 영역만 딱 맞게 잘라서 저장합니다. 보고서에 넣을 때 여백을 일일이 자를 필요가 없어집니다.

특히 subplot을 사용할 때 더 유용합니다. 기본 설정으로 저장하면 빈 공간이 많은데, tight 옵션을 쓰면 깔끔하게 정리됩니다.

투명 배경의 활용 transparent=True를 설정하면 배경이 투명한 PNG 파일이 생성됩니다. 이것을 파워포인트나 웹페이지에 올리면 배경색과 자연스럽게 어울립니다.

흰색 배경으로 저장하면 배경색이 다를 때 네모난 흰색 박스가 보여서 어색합니다. 단, 투명 배경은 PNG 포맷에서만 지원됩니다.

JPEG는 투명도를 지원하지 않습니다. 포맷의 선택 PNG, PDF, SVG 등 여러 포맷이 있습니다.

어떤 것을 선택해야 할까요? PNG는 래스터 이미지로, 픽셀로 구성됩니다.

웹이나 문서에 넣기 좋지만 확대하면 깨집니다. PDFSVG는 벡터 이미지로, 수학적으로 정의되어 아무리 확대해도 깨지지 않습니다.

논문이나 출판물에는 PDF가 좋습니다. 웹용으로는 PNG나 SVG가 적합합니다.

SVG는 일러스트레이터나 잉크스케이프에서 편집할 수도 있습니다. 코드 분석 먼저 그래프를 그립니다.

그다음 plt.show()를 호출하기 전에 plt.savefig()를 호출해야 합니다. 순서가 중요합니다.

show()를 먼저 호출하면 화면에 표시되면서 figure가 초기화되어 저장이 안 될 수 있습니다. **plt.savefig('sales_report.png', dpi=300, bbox_inches='tight', transparent=True)**에서 각 옵션을 봅시다.

첫 번째 인자는 파일 이름입니다. 확장자로 자동으로 포맷을 결정합니다.

dpi=300은 고해상도, bbox_inches='tight'는 여백 제거, transparent=True는 투명 배경입니다. 같은 그래프를 여러 포맷으로 저장할 수도 있습니다.

PNG는 프레젠테이션용, PDF는 인쇄용, SVG는 웹용으로 각각 저장하면 편리합니다. 실무 활용 김개발 씨의 팀에서는 주간 보고서를 자동으로 생성하는 스크립트를 만들었습니다.

그래프를 PNG로 저장하여 이메일에 첨부하고, PDF로도 저장하여 아카이브합니다. 한 번 실행으로 모든 포맷이 준비됩니다.

또한 웹 대시보드에는 SVG를 사용합니다. 사용자가 확대해도 선명하고, 파일 크기도 작아서 로딩이 빠릅니다.

파일 크기 고려 고해상도 이미지는 파일 크기가 큽니다. dpi=300인 복잡한 그래프는 몇 MB가 될 수 있습니다.

이메일에 첨부하거나 웹에 올릴 때는 적절한 균형을 찾아야 합니다. 웹용이라면 dpi=150 정도로도 충분합니다.

또는 PNG를 저장한 후 tinypng 같은 도구로 압축할 수도 있습니다. 흔한 실수 plt.show() 후에 plt.savefig()를 호출하면 빈 이미지가 저장됩니다.

항상 savefig를 먼저, show를 나중에 호출해야 합니다. 또는 show 없이 savefig만 사용할 수도 있습니다.

파일 이름에 경로를 포함할 수 있습니다. './reports/sales.png'처럼 폴더를 지정하면 해당 폴더에 저장됩니다.

폴더가 없으면 에러가 나니 미리 만들어두어야 합니다. 정리하며 김개발 씨는 savefig 옵션을 제대로 설정한 후 그래프를 다시 저장했습니다.

이번에는 프레젠테이션에 넣어도 선명하고 깔끔합니다. "이제 제대로 된 그래프를 만들 수 있게 됐어요!" 그래프를 저장할 때는 용도에 맞는 포맷과 옵션을 선택하세요.

품질 좋은 이미지가 전문성을 높입니다.

실전 팁

💡 - facecolor='white'로 배경색을 명시적으로 설정하면 일관성이 유지됩니다

  • pad_inches=0.1로 저장 시 여백을 최소화할 수 있습니다

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Python#Matplotlib#Visualization#DataAnalysis#Plotting

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.