
벌써 6주차입니다
그렇다는건....
방학이 얼마 안남았다는 이야기네요 ㅜ
저는 특히나 직전학기가 휴학이었어서
학교가기가 너무 싫어요
아무튼... 어느새 밝아온 6주차 지금 시작합니다
06-1. 객체지향 API로 그래프 그리기
이 소단원에서는 조금 복잡한 그래프를 시작화하는 법을 배운다.
대표적으로 파이썬에서 그래프를 그리는 방법에는 크게 두가지가 있는데
1. matplotlib의 pyplot방식
- Ch.5에서 주로 사용했던 방식
plt.(그래프함수)를 이용하여 그리는 방식이다.
import matplotlib.pyplot as plt
plt.plot([1, 4, 9, 16])
plt.title('simple line graph')
plt.show()
2. 객체지향 API방식
- subplot을 그릴 때 이용했던 방식
-> 복잡한 그래프를 그리는 경우에 이 방식을 사용하는 것이 좋다.
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([1, 4, 9, 16])
ax.set_title('simple line graph')
fig.show()
# 이 방식의 경우 plt.show 가 아닌 fig.show를 사용한다.
*객체지향 : 프로그램을 객체(Object)라는 독립된 단위로 쪼개서, 그 객체들끼리 상호작용하도록 만드는 설계 방식을 뜻함
- matplotlib의 기본 설정 바꾸기
1) rcParams[]
저번 단원에서도 다루었던 기본값 확인/ 재설정이 가능한 함수
2) rc()
한 그룹 내 여러 설정을 동시에 지정할 수 있는 함수
-> 이 두가지 함수를 이용하여 폰트 설정 해보기
#rcParams
plt.rcParams['font.family'] = 'NanumGothic'
#rc
plt.rc('font', family='NanumBarunGothic', size=11)
rc('설정할 그룹','그룹 하위속성1','그룹 하위속성2')
*폰트 설정 코드
# 노트북이 코랩에서 실행 중인지 체크합니다.
import sys
if 'google.colab' in sys.modules:
!echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
# 나눔 폰트를 설치합니다.
!sudo apt-get -qq -y install fonts-nanum
import matplotlib.font_manager as fm
font_files = fm.findSystemFonts(fontpaths=['/usr/share/fonts/truetype/nanum'])
for fpath in font_files:
fm.fontManager.addfont(fpath)
# 링크는 폰트 파일을 ttf파일을 다운로드해서 내 컴퓨터에 저장되어 있는 파일 경로를 fontpaths에 넣으면 됨
#폰트를 다운로드 받을 때.. 아마 코드가 있을거임
#맷플롯립에서 사용할 수 있는 폰트의 전체 목록 확인하려면(이미 내 시스템에 설치된 폰트들)
from matplotlib.font_manager import findSystemFonts
findSystemFonts()
- 객체지향 API로 산점도 만들기
많은 데이터 중 고유한 데이터의 개수를 뽑아내는 함수는 value_count()함수였다.
그렇지만 고유한 데이터는 너무 많고 이 중 몇 개만 뽑아내려고 할 때
전체 데이터에서 선택된 데이터만 뽑아내려면 isin() 메서드를 사용한다.
#출판사가 top30_pubs.index리스트에 들어있다면 True, 아니면 False로 불리언 배열 출력
top30_pubs_idx = ns_book7['출판사'].isin(top30_pubs.index)
top30_pubs_idx
- 산점도 마.꾸(마커 꾸미기)
scatter()함수의 매개변수를 통해 마.꾸 가능
s : 마커의 크기 지정
실수로 설정하면 모든 마커가 같은 크기, 데이터와 같은 길이의 배열로 설정하면 데이터마다 마커의 크기가 달라짐
일정 수를 곱하면 데이터 값에 따라 마커 크기의 차이가 커진다
alpha : 투명도 조정
값이 클수록 진하고, 작을수록 연함
edgecolor : 마커 테두리 색 조정
기본값은 마커와 같은 색인 'face' , 'k'는 검은색
linewidths : 마커 테두리 선 두께 조정
기본값은 1.5
c : 산점도 색 조정
일정 색을 지정하면 모든 마커가 같은 색, 데이터와 같은 길이의 배열을 전달하면 각 데이터를 다른 색깔로 그릴 수 있음
cmap : 값에 따라 색상을 다르게 표현
기본값은 'viridis' - 큰 값은 노랑, 작은 값은 녹색
자주 쓰는 값은 'jet' - 큰 값은 빨강, 작은 값은 파랑
*컬러막대와 같이 출력하기
산점도 색을 조정한 후, 어떤 색이 큰 값을 나타내는 것인지를 시각적으로 나타내기 위해 컬러막대와 같이 출력하면 좋다.
컬러막대는 scatter() 함수가 반환하는 객체를 colorbar() 메서드에 전달하면 된다.
**subplot 안의 산점도에서 colorbar를 만들고 싶으면 ax매개변수에 그래프의 위치를 전달
ex) fig.colorbar(sc, ax=axes[0,1])
fig, ax = plt.subplots(figsize=(10, 8))
sc = ax.scatter(ns_book8['발행년도'], ns_book8['출판사'],
linewidths=0.5, edgecolors='k', alpha=0.3,
s=ns_book8['대출건수']**1.3, c=ns_book8['대출건수'], cmap='jet')
ax.set_title('출판사별 발행도서')
fig.colorbar(sc)
fig.show()
[기본과제]

06-2. 맷플롯립의 고급 기능 배우기
1) 한 개의 피겨에 선 그래프 여러개 그리기
-> 하나의 피겨에 대해 plot 함수를 여러번 호출하면 됨
*각 line에 대한 정의 필요
line1 = ns_book9[ns_book9['출판사'] == '황금가지']
line2 = ns_book9[ns_book9['출판사'] == '비룡소']
fig, ax = plt.subplots(figsize=(8, 6))
ax.plot(line1['발행년도'], line1['대출건수'], label='황금가지')
ax.plot(line2['발행년도'], line2['대출건수'], label='비룡소')
ax.set_title('년도별 대출건수')
ax.legend()
#legned()메서드를 호출하면 각 그래프의 label을 범례로 출력
fig.show()
#for문 사용도 가능하다
fig, ax = plt.subplots(figsize=(8, 6))
for pub in top30_pubs.index[:5]:
line = ns_book9[ns_book9['출판사'] == pub]
ax.plot(line['발행년도'], line['대출건수'], label=pub)
ax.set_title('년도별 대출건수')
ax.legend()
ax.set_xlim(1985, 2025)
#x축 범위를 설정함으로써 그래프 위치 수정 가능(0인 값이 앞쪽에 많다거나..등등)
fig.show()
이렇게 코드를 짜면

이런 그래프가 출력된다.
하지만 선 그래프도 여러개가 섞여 있으면 구별이 어렵다는 단점이 있는데...
이러한 단점때문에 생겨난 그래프가 '스택 영역 그래프'이다.
[추가과제]
2)스택 영역 그래프
스택 영역 그래프는 하나의 선 그래프 위에 다른 선 그래프를 차례대로 쌓는 형식이다.
따라서 그래프 사이의 간격이 y축 값이 된다
이 그래프를 그리기 위해서는
1. pivot_table()메서드로 x축에 해당하는 열의 값을 열로 바꾸기
2. x축에 해당하는 열을 리스트 형태로 바꾸기
3. stackplot() 메서드로 스택 영역 그래프 그리기
의 과정이 필요합니다.
- 피벗테이블
많은 양의 데이터를 원하는 기준(행, 열, 값, 필터 등)에 따라 재구성해서 볼 수 있게 해준다
pivot_table()메서드는 index ,columns 매개변수에 특정 열을 지정하여 새로운 형식의 테이블을 만들 수 있다.
ns_book10 = ns_book9.pivot_table(index='출판사', columns='발행년도')
ns_book10.head()
#출판사, 발행년도, 대출건수가 있던 table에 출판사를 인덱스로 넣고, 발행년도를 컬럼으로 넣으면
#값이었던 발행년도들이 열 이름으로 변환되고, 값에는 대출건수만이 존재한다.

* 다만 유의점은 열이 다단으로 만들어진다는 것이다. '1947'열이 아니라 ('대출건수', 1947)열이다.
**
이렇게 다단으로 이루어진 열에서 일부만 따오고 싶다면 get_level_values()메서드를 사용한다.
괄호 안에는 열 이름 튜플의 인덱스가 들어간다.
ns_book10.columns[:10]
ㄴMultiIndex([('대출건수', 1947),
('대출건수', 1974),
('대출건수', 1975), (중략)])
year_cols = ns_book10.columns.get_level_values(1)
#괄호 안에 인덱스
year_cols
ㄴIndex([1947, 1974, 1975, 1976, 1977, (중략)])
***피벗테이블에서 열 이름을 다단으로 설정하고 싶지 않다면 매개변수 value에 값을 설정해주면 된다.
특히 그룹바이로 따로 값을 만들고, 피벗테이블을 만들지 않고 피벗테이블 함수에서 바로 만들수도 있다.
import numpy as np
ns_book11 = ns_book7[top30_pubs_idx].pivot_table(
index='발행년도', columns='출판사',
values='대출건수', aggfunc=np.sum)
#value에 값 지정, 이 값이 만약 계산이 필요한 값이라면 aggfunc에 넘파이 형식의 집계방식 설정.
#aggfunc의 기본값은 평균이다
ns_book11.loc[2000:2005]
=> 스택 영역 그래프 그리기
fig, ax = plt.subplots(figsize=(8, 6))
ax.stackplot(year_cols, ns_book10.loc[top10_pubs].fillna(0), labels=top10_pubs)
#(x축 리스트, 피벗테이블[원하는 행만 선택],label)
#이 경우 피벗테이블 뒤에 fillna(0)은 앞서 만든 피벗테이블에 nan값이 있었기 때문.
ax.set_title('년도별 대출건수')
ax.legend(loc='upper left')
#legend()메서드에 loc매개변수로 범례의 위치를 조정할 수 있다.
ax.set_xlim(1985, 2025)
fig.show()
+) 판다스를 이용해서 그리기
앞서 만들었던 것과 인덱스/열 이름을 바꿔서 피벗테이블을 만든다.
'출판사'가 열 이름으로 가고, 연도가 인덱스로 오도록 피벗테이블을 만든 후 plot.area() 메서드를 호출하여 그래프를 그린다
fig, ax = plt.subplots(figsize=(8, 6))
ns_book11[top10_pubs].plot.area(ax=ax, title='년도별 대출건수',
xlim=(1985, 2025))
#ax매개변수에 맷플롯립의 axes객체를 전달해야 한다.
ax.legend(loc='upper left')
fig.show()
3) 한 개의 피겨에 막대그래프 여러 개 그리기
-> bar() 메서드를 여러 번 호출하기❌
plot()과 마찬가지로 여러 번 호출하면 되지 않을까? 싶겠지만
막대 그래프의 경우 여러 번 함수를 그리면 막대들이 다 겹쳐서 그려지므로 안된다.
따라서 대안 1. 두께를 얇게 해서 동시에 그리기
원래는 0.8인 막대그래프의 너비를 0.4로 반 줄여서, 두 막대그래프를 각각 앞뒤로 0.2씩 이동시키면
얇은 막대그래프 두개가 나란히 그려진다.
fig, ax = plt.subplots(figsize=(8, 6))
ax.bar(line1['발행년도']-0.2, line1['대출건수'], width=0.4, label='황금가지')
#막대위치변경은 x축 설정에 포함
ax.bar(line2['발행년도']+0.2, line2['대출건수'], width=0.4, label='비룡소')
ax.set_title('년도별 대출건수')
ax.legend()
fig.show()
대안 2. 스택 막대 그래프 그리기
막대 그래프는 stackplot()같은 메서드가 없다.
-> bottom매개변수를 활용/ 전체 길이 누적 등의 방법을 이용해 수동으로 그래프를 쌓아야 한다.
#방법1. 2번 그릴 때 1번 부터 시작, 3번 그릴 때 2번부터 시작 등
height1 = [5, 4, 7, 9, 8]
height2 = [3, 2, 4, 1, 2]
plt.bar(range(5), height1, width=0.5)
plt.bar(range(5), height2, bottom=height1, width=0.5)
plt.show()
#방법2. 누적 길이를 만들어놓고 그리기
height3 = [a + b for a, b in zip(height1, height2)]
#1과 2를 합친 길이인 3을 일단 만듦
plt.bar(range(5), height3, width=0.5)
#3부터 그리고(긴 것부터 그려야함)
plt.bar(range(5), height1, width=0.5)
#1을 그리면 두 막대그래프가 겹쳐져 그려지면서 자연스럽게 2번이 1번 위로 그려짐
plt.show()
*데이터의 값을 누적되게 만들려면 cumsum()메서드를 사용하면 된다.
ns_book12 = ns_book10.loc[top10_pubs].cumsum()
#이를 이용해 스텍 막대 그래프 만들기
fig, ax = plt.subplots(figsize=(8, 6))
for i in reversed(range(len(ns_book12))):
#range()함수로 행 길이만큼 인덱스를 만들고 reversed()로 인덱스 역순으로 반복
#df에 len함수를 쓰면 행 개수 출력
bar = ns_book12.iloc[i] # 행 추출
label = ns_book12.index[i] # 출판사 이름 추출
ax.bar(year_cols, bar, label=label)
ax.set_title('년도별 대출건수')
ax.legend(loc='upper left')
ax.set_xlim(1985, 2025)
fig.show()
**판다스로는 더 편하게 스택 막대 그래프를 그릴 수 있다
fig, ax = plt.subplots(figsize=(8, 6))
ns_book11.loc[1985:2025, top10_pubs].plot.bar(
ax=ax, title='년도별 대출건수', stacked=True, width=0.8)
#ax매개변수에 axes객체 설정
#기본적으로 막대그래프를 나란히 출력하나 stacked=True이면 스택 막대 그래프를 그려줌
ax.legend(loc='upper left')
fig.show()
4) 원 그래프
-> pie() 메서드를 이용하여 그림
fig, ax = plt.subplots(figsize=(8, 6))
ax.pie(data, labels=labels)
#데이터만 넣으면 알아서 비율 맞춰서 원그래프를 그려줌
#인덱스를 넣고 싶으면 labels에 넣으면 됨
ax.set_title('출판사 도서비율')
fig.show()
*원그래프는 기본적으로 3시방향부터 반시계로 그려진다.
**시작 방향을 바꾸고 싶으면 startangle매개변수를 바꾸면 된다. 설정한 각도만큼 반시계방향으로 뒤로 가서 그래프 시작
-기타 원 그래프 설정
autopct 매개변수
: 원 그래프의 비율을 표시할 포맷팅 문자열 전달(정규표현식 이용)
explode 매개변수
: 강조하고 싶은 부분을 일정 반지름 비율만큼 떨어뜨려 부각
각 데이터를 중심에서 떨어뜨리고 싶은 만큼의 반지름 비율을 적은 데이터 길이와 같은 리스트 전달
fig, ax = plt.subplots(figsize=(8, 6))
ax.pie(data, labels=labels, startangle=90,
autopct='%.1f%%', explode=[0.1]+[0]*9)
#%.1f%%라는 정규표현식 전달 / explode는 10개의 데이터 개수와 맞게 요소가 10개인 리스트 전달
ax.set_title('출판사 도서비율')
fig.show()
'혼공단' 카테고리의 다른 글
| [혼공분석] 14기 혼공학습단 회고 (0) | 2025.08.19 |
|---|---|
| [혼공분석] 5주차_Ch.5 데이터 시각화하기 (4) | 2025.08.11 |
| [혼공분석] 4주차_Ch.4 데이터 요약하기 (4) | 2025.08.03 |
| [혼공분석] 3주차_ch.03 데이터의 정제 (2) | 2025.07.25 |
| [혼공분석] 2주차_Ch2. 데이터 수집 (7) | 2025.07.12 |