[TIL] 5일차 TIL(20230210) - Matplotlib를 이용한 데이터 시각화
[TIL] 5일차 TIL(20230210) - Matplotlib를 이용한 데이터 시각화
1. 막대그래프
- plt.bar(x, y)
- plt.barh(x, y): 막대그래프를 가로로 그려줌
1.1 막대그래프 옵션
- width: 막대 폭 지정(0~1사이의 실수, default: 0.8)
- height: 가로막대 폭 지정
- color = [컬러 리스트]: 막대마다 다른 색 지정
- edgecolor: 막대 테두리 색상/ linewidth: 막대 테두리 두께
plt.bar(df1['요일'], df1['매출액'], color = ['r','orange','y','g','b','navy','violet'],
edgecolor = 'gray');
- hatch: 막대에 패턴 지정 ex) '/', '//', '|', '-', '+', 'x', 'o', 'O', '.', '*'
- set_hatch(기호): 막대 그래프를 객체로 받아 막대마다 다른 패턴을 지정할 수 있음
ex) bars = plt.bar(x, y)
bars[0].set_hatch('*')
bars = plt.bar(df1['요일'], df1['매출액'], color = ['r','orange','y','g','b','navy','violet'],
edgecolor ='gray');
#각 막대에 접근
bars[0].set_hatch('.')
bars[1].set_hatch('..')
bars[2].set_hatch('+')
bars[4].set_hatch('*')
bars[5].set_hatch('/')
bars[6].set_hatch('//')
- align = center/edge: 막대 위치 지정,
edge로 지정하면 막대의 왼쪽 끝과 틱을 맞추기 때문에 오른쪽 끝을 맞추고 싶으면 width를 음수로 지정
막대의 위치를 지정하는 옵션과 막대의 두께를 조정하여 축이 동일한 두개의 그래프를 동시에 그리는 것이 가능
plt.bar(df1['요일'], df1['매출액'], width = -0.4, align = 'edge', label = 'store1');
plt.bar(df2['요일'], df2['매출액'], width = 0.4, align = 'edge', label = 'store2');
plt.legend()
plt.title('두 매장의 요일별 매출액 평균', size = 15)
plt.grid(axis = 'y', ls=':')
plt.show()
2. 산점도
- 점의 위치, 크기, 색깔로 정보를 표현할 수 있음(=버블차트)
- plt.scatter(x, y)
2.1 산점도 옵션
- s = 크기 리스트: 공통된 크기로 지정할 수도 있고, 점마다 다른 크기로 지정할 수도 있음
- c = 색깔 리스트
- cmap = 컬러맵명: 크기에 따라 자동으로 색을 다채롭게 지정해주는 컬러맵을 사용할 수 있음
plt.colorbar()를 함께 사용해주면 컬러맵의 정보를 함께 표기
- alpha: 0과 1사이의 값으로 투명도 표현
plt.scatter(x, y, s = [100, 200, 500, 80, 300], c = y, cmap = 'spring')
plt.colorbar();
3. 히트맵
- 색으로 값의 크기를 표현하는 그래프
- plt.pcolor(2차원 데이터)
- cmap을 지정하여 색상 테마 변경 가능
plt.pcolor(df, cmap = 'Blues')
plt.colorbar();
3.1 seaborn패키지를 이용한 히트맵 그리기
- sns.heatmap(2차원 데이터)
- annot = True: 수치 표시
- fmt = 'd': 수치를 정수로 표시
import seaborn as sns
sns.heatmap(titanic_pivot, cmap = 'Blues', annot = True, fmt = 'd');
4. 히스토그램
- 자료를 일정 구간으로 나누어 구간별 값의 개수를 나타냄
- plt.hist(data)
plt.hist(scores);
4.1 히스토그램 옵션
- bins: 구간의 개수 지정(default = 10)
- cumulative = True: 누적 히스토그램 그리기
- range = (min, max): x축의 범위 지정, 해당 범위만 잘라서 표현
- density = True: 밀도 표시, 도수를 총 개수로 나눈 수치
- orientation = 'horizontal': 가로 히스토그램
- histtype = 'step': 선만 표시, 여러개의 히스토그램을 비교할 때 겹쳐지지 않도록 하기 위해서 많이 사용
plt.hist(scores, histtype = 'step');
- rwidth: 막대의 폭 지정(0~1사이)
- color: 막대의 색/ alpha: 투명도
- edgecolor(ec): 테두리 선 색 지정/ linewidth(lw): 테두리 선 두께 지정/ linestyle(ls): 테두리 선 종류 지정
- hatch: 패턴 지정
plt.hist(scores, rwidth = 0.9, alpha = 0.5, ec = 'k', ls = ':')
plt.xticks(range(0, 110, 10))
plt.grid(axis = 'y', ls = ':')
plt.xlabel('점수')
plt.ylabel('인원')
plt.title('점수대별 인원 분포', size = 15)
plt.show()
5. 박스플롯
- 데이터로부터 얻어진 5가지 요약통계량을 사용해서 그리는 그래프
- 최소값, Q1(제 1 사분위 수), 중앙값, Q3(제 3 사분위 수), 최대값
- IQR = Q3 - Q1(사분위 수 범위)
- Q1 - 1.5*IQR보다 작거나, Q3 + 1.5*IQR보다 큰 값을 이상치로 간주하여 점으로 표현
- plt.boxplot(data)
5.1 박스플롯 옵션
- showmeans = True: 평균값을 녹색 삼각형으로 그래프에 표시
- meanline = True: 평균값을 녹색 점선으로 표시
- vert = False: 박스플롯을 수평으로 그림
plt.boxplot(scores, showmeans = True, meanline = True);
5.2 여러개의 박스플롯 그리기
- 여러개의 데이터의 박스플롯을 동시에 표현하기 위해서는 데이터들을 리스트로 묶어서 넣어주면 됨
- plt.boxplot([data1, data2, data3], labels = [d1, d2, d3])
plt.boxplot([iris['sepal_length'], iris['sepal_width'], iris['petal_length'], iris['petal_width']],
labels = ['sapal_length', 'sepal_width', 'petal_length', 'petal_width'],
showmeans = True, meanline = True)
plt.grid(axis = 'y', alpha = 0.5)
plt.show()
6. 바이올린플롯
- 데이터의 주요 정보(최대, 최소값 등)과 데이터의 분포를 나타내주는 그래프
- plt.violinplot(data)
6.1 바이올린플롯 옵션
- showextrema = True: 최대값/최소값에 직선 표시
- showmeans = True: 평균값에 직선 표시
- showmedians = True: 중앙값에 직선 표시
- quantiles = [0에서 1사이의 실수리스트]: 분위 값 표시
plt.violinplot(scores, showmeans = True, showmedians = True);
- 바이올린플롯 객체를 받은 뒤 스타일을 지정할 수 있음
- 플롯명['bodies'][index].set_facecolor(color): index번째 플롯의 분포 색 지정
- 플롯명['cmins'/'c,maxes'].set_edgecolor(color):최소/최대값 직선의 색 지정
- 플롯명['cbars'].set_edgecolor(color): 플롯 가운데 직선의 색 지정
- 플롯명['cmedians'/'cmeans'/'cquantiles'].set_edgecolor(color): 중앙값/평균/분위수 직선의 색 지정
v1 = plt.violinplot(scores, quantiles = [0.25, 0.75], showmeans = True, showmedians = True);
v1['bodies'][0].set_facecolor('r')
v1['cmedians'].set_edgecolor('violet')
v1['cmeans'].set_edgecolor('red')
v1['cquantiles'].set_edgecolor('k')
6.2 여러개의 바이올린플롯 그리기
- plt.violinplot([data1, data2, data3])
- 각 플롯이 나타내는 항목을 x틱을 통해 표현할 수 있음
plt.xticks(range(1, 항목의 수+1, 1), labels = [항목 이름 리스트])
data_list = [iris['sepal_length'], iris['sepal_width'], iris['petal_length'], iris['petal_width']]
v2 = plt.violinplot(data_list, showmeans = True, showmedians = True, quantiles = [[0.25, 0.75]]*4)
v2['bodies'][0].set_facecolor('r')
v2['bodies'][1].set_facecolor('g')
v2['bodies'][2].set_facecolor('c')
v2['cmins'].set_edgecolor('r')
v2['cmaxes'].set_edgecolor('r')
plt.xticks(range(1, 5, 1), labels = iris.columns[:-1])
plt.grid(axis = 'y', ls = ':')
plt.show()
7. 파이차트
- 전체에 대한 각 부분의 비율을 부채꼴 모양으로 나타낸 그래프
- plt.pie(data, labels = [label리스트])
7.1 파이차트 옵션
- labeldistance: 그래프로부터 레이블을 얼마만큼 떨어뜨려서 표시할것인지(1보다 작으면 내부에 표시)
- autopct = '%소수점자리수%%' ex) %.1f%%, 소수점 첫째자리까지 표시
- pctdistance : 반지름을 1이라고 했을 때 중심으로부터 비율을 표시할 거리
- explode = [돌출정도 리스트]: 모든 레이블에 대하여 표시, 돌출하지 않을 시 0 ex)[0.05, 0, 0, 0]
- colors = [색상 리스트]
plt.pie(Personnel, labels = blood_type, labeldistance = 1.1, autopct = '%.1f%%',
explode = [0.05, 0, 0, 0],
colors = ['lightcoral', 'gold', 'greenyellow', 'skyblue']);
- startangle = 시작각도: 기본은 3시방향, 3시방향으로부터 반시계 방향으로 해당 각도만큼 이동하여 시작
- counterclock = True/False: 반시계방향/시계방향
- radius: 원의 반지름 크기, default = 1
- plt.legend()를 이용하여 범례 표현
- wedgeprops = {'ec': 테두리 컬러, 'lw': 선 두께, 'ls': 선 스타일, 'width': 반지름에 대한 비율}:
반지름에 대한 비율만큼 가운데가 도려내진 도넛 모양의 그래프를 반환
- textprops= {'fontsize': 폰트 크기, 'color': 폰트 컬러, 'rotation': 폰트 회전각도}
plt.pie(Personnel, labels = blood_type, labeldistance = 1.1, autopct = '%.1f%%',
explode = [0.05, 0, 0, 0],
colors = ['lightcoral', 'gold', 'greenyellow', 'skyblue'],
startangle = 90,
counterclock = False,
wedgeprops = {'ec': 'k', 'lw': 1, 'ls': ':', 'width': 0.7},
textprops = {'fontsize': 10, 'color': 'k'}
)
plt.legend(loc = (1, 0.5));
8. 그래프 꾸미기 옵션
8.1 제목
- plt.title('제목명')
- loc: 제목 위치('left', 'right', 'center')
- pad: 타이틀과 그래프와의 간격
- font: 폰트 지정
- color: 폰트 색상/ fontsize: 폰트 크기/fontweight: 폰트 굵기('normal','bold','heavy','light','ultrabold','ultralight')
8.2 레이블, x축, y축 이름
- plt.xlabel('레이블명'), plt.ylabel('레이블명')
- loc : 위치(x축 = 'left','center','right' /y축 = 'bottom', 'center','top')
- labelpad: 레이블과 그래프와의 간격
8.3 그리드
- plt.grid(True)
- axis: 그리드 방향
- linestyle(ls), linewidth(lw), color, alpha(투명도) 옵션 지정 가능
plt.plot(df['월'], df['몸무게'], 'ro--', lw = 3, ms = 7)
plt.title('월별 몸무게 변화')
plt.xlabel('월', loc = 'right', color = 'b')
plt.ylabel('몸무게(kg)', loc = 'top', color = 'b')
plt.grid(color = 'skyblue', alpha = 0.5, ls = 'dotted')
plt.show()
8.4 축 범위
- plt.xlim(min, max)
- plt.ylim(min, max)
8.5 눈금(tick) 설정
- plt.xticks(틱 리스트, label = 레이블 리스트)
- plt.yticks(틱 리스트, label = 레이블 리스트)
- 각 눈금에 보여줄 레이블을 지정할 수 있음, 눈금과 레이블의 개수가 동일해야 함
8.5.1 눈금(tick) 스타일 지정
- plt.tick_params()
- direction: 틱 위치(in, out, inout)
- length: 틱의 길이/ width: 틱의 두께
- color: 틱 색상/ labelcolor: 틱 레이블 색상/ colors: 틱과 틱 레이블 색상(동일하게 지정)
- pad: 틱과 레이블 사이의 거리
- labelsize: 틱 레이블 크기
- axis: 축 지정(축별로 옵션 따로 설정 가능)
x = df['월']
y = df['몸무게']
plt.plot(x,y,'bo-', mfc='r',mec='r')
# title
plt.title('월별 몸무게 변화', fontweight = 'bold')
# 축 레이블
plt.xlabel('월')
plt.ylabel('몸무게(kg)')
# 그리드
plt.grid(ls = ':')
#축 지정
plt.xticks(range(13), label = xticks_lable)
plt.yticks(range(50, 101, 10), label = yticks_lable)
plt.tick_params(direction = 'in', colors = 'g', width = 5)
plt.show()
8.6 범례(legend)
- plt.legend()
- 여러 개의 플롯을 동시에 그리는 경우, 각 그래프가 무엇을 표시하는지 보여주기 위해 범례를 추가
- 그래프에 레이블을 지정한 뒤, 범례를 추가해야 함
- 범례의 위치는 따로 설정하지 않으면 그래프에 따라 최적의 위치에 자동으로 표시
8.6.1 범례 옵션 지정
- loc = 위치번호/위치이름
위치명 | 위치번호 |
best | 0 |
upper right | 1 |
upper left | 2 |
lower left | 3 |
lower right | 4 |
right | 5 |
center left | 6 |
center right | 7 |
lower center | 8 |
upper center | 9 |
center | 10 |
- loc = (x, y)로 좌표를 직접 지정해서 사용 가능, 좌표는 범례의 왼쪽 아래 꼭지점 기준
ex) 그래프 외부에 범례를 표현하고 싶다면 loc = (1.05, 0.8)등으로 x>1로 지정
- ncol : 범례에서 표현할 열 개수
- frameon = True/False: 테두리 유무
- shadow = True/False: 그림자 유무
- facecolor: 바탕색 지정
- edgecolor : 테두리색 지정
#두 그래프 그리기
plt.plot(df1['월'],df1['몸무게'], label = 'James')
plt.plot(df2['월'],df2['몸무게'], label = 'Amy')
# 그래프 제목
plt.title('월별 몸무게 변화', fontsize = 15, pad = 10)
# 축 라벨
plt.xlabel('월', fontsize = 12)
plt.ylabel('몸무게(kg)', fontsize = 12)
# x축 틱 : 1월, 2월, 3월,...,12월
plt.xticks(range(0, 14), labels = xtick_label)
# y축 틱 : 30kg, 35kg, 40kg, ..., 90kg
plt.yticks(range(30, 95, 5), labels = ytick_label)
# 그리드
plt.grid()
#범례
plt.legend(loc = 0, ncol = 2, frameon = True, shadow = True, facecolor = 'ivory')
plt.show()
8.7 그래프 영역 채우기(강조하기)
- plt.fill_between(x[슬라이싱], y[슬라이싱]): 가로 방향으로 채우기(그래프 아랫부분)
- plt.fill_betweenx(y[슬라이싱], x[슬라이싱]): 세로 방향으로 채우기(그래프 왼쪽부분)
- plt.fill_between(x[슬라이싱], y1[슬라이싱], y2[슬라이싱]): 두 그래프 사이의 영역 채우기
- plt.fill([x축 좌표들], [y축 좌표들])
- color, alpha, hatch 등 기존에 사용하던 옵션들 적용 가능
x = [1,2,3,4]
y1 = [1,3,4,6]
y2 = [2,4,7,9]
plt.plot(x,y1)
plt.plot(x,y2)
plt.fill_between(x[1:3], y1[1:3], y2[1:3], alpha = 0.5)
plt.show()
x = [1,2,3,4]
y = [1,4,3,6]
plt.plot(x,y)
plt.grid()
plt.fill([1.75, 2.25, 2.25, 1.75], [3.5, 3.5, 4.5, 4.5], alpha = 0.1)
plt.show()
8.8 공통 스타일 지정하기
- 자주 사용하는 옵션이 있다면 기본 설정에서 변경해줘서 매번 옵션을 따로 지정하지 않고 계속 사용할 수 있음
- plt.rcParams['figure.figsize']: 그래프 크기 지정
- plt.rcParams['axes.titlesize']: 제목 크기 지정
- plt.rcParams['axes.grid'] = True: 그리드 표시 유무
- plt.rcParams['grid.linestyle']: 그리드 선 스타일 지정
- plt.rcParams['xtick.direction'] = 'in': 눈금 위치 지정
- plt.rcParams['lines.marker'] ='o': 마커의 종류 + 마커가 기본적으로 그려지도록 지정
이 외의 다양한 옵션들은 plt.rcParams를 통해 확인하고, 지정할 수 있음
9. 그래프 여러개(서브플롯) 그리기
- fig = plt.figure를 이용해 전체 도화지의 옵션을 지정해주고 추가적인 설정이 가능함
- fig.suptitle('제목'): 전체 그래프의 제목 표시
- fig.tight_layout(): 그래프의 간격, 너비를 최적화
9.1 격자를 지정하여 격자마다 그래프 그리기
- ax1 = plt.subplot(전체 행 개수, 전체 열 개수, 그래프 순서, sharex = ax)
- ax1 = fig.add_subplots(전체 행 개수, 전체 열 개수, 그래프 순서, sharex = ax)
ax1.plot(그래프 그리기)
fig = plt.figure(figsize = (10, 7))
plt.subplot(221)
plt.plot(df1['x'], df1['y'], 'ro')
plt.title('ax1')
plt.subplot(222)
plt.plot(df2['x'], df2['y'], 'o', color = 'orange')
plt.title('ax2')
plt.subplot(223)
plt.plot(df3['x'], df3['y'], 'o', color = 'g')
plt.title('ax3')
plt.subplot(224)
plt.plot(df4['x'], df4['y'], 'o');
plt.title('ax4')
fig.suptitle('Anscombe', size = 20)
fig.tight_layout()
# 1) figure 객체를 생성한다.
fig = plt.figure(figsize = (9, 6), facecolor = 'ivory')
# 2) 서브플롯을 그릴 axes 객체를 생성한다.
# 4) 축 공유하기 : 어떤 axes의 축을 공유할 것인지 지정한다.
ax1 = fig.add_subplot(2, 2, 1)
ax2 = fig.add_subplot(2, 2, 2, sharex = ax1)
ax3 = fig.add_subplot(2, 2, 3, sharex = ax1)
ax4 = fig.add_subplot(2, 2, 4)
# 3) axes 객체에 그래프를 그린다.
ax1.plot(df1['x'], df1['y'], 'o', label = 'ax1')
ax2.plot(df2['x'], df2['y'], '^', label = 'ax2')
ax3.plot(df3['x'], df3['y'], 'g*', label = 'ax3')
ax4.plot(df4['x'], df4['y'], 's', color = 'orange', label = 'ax4')
# 4) 틱 변경하기
ax4.set_xticks(range(1, 20, 1))
ax4.set_yticks(range(1, 15, 1))
# 5) 범례 표시하기
ax1.legend(loc=2)
ax2.legend(loc=2)
ax3.legend(loc=2)
ax4.legend(loc=2)
# 6) figure 제목 추가하기
fig.suptitle('Anscombe', size = 20)
# 8) 그래프 크기,간격 최적화하기
fig.tight_layout()
plt.show()
9.2 위치, 크기 각각 지정하여 그래프 그리기
- ax = fig.add_axes([left, bottom, width, height])를 이용하여 위치, 크기를 지정한 그래프 추가
- 각각의 수치는 모두 전체 도화지를 1이라고 했을 때의 상대적 크기, 위치를 나타냄
# 1)figure 객체를 생성한다.
fig = plt.figure(figsize = (8, 6))
# 2) figure객체의 add_axes 메소드로 위치와 크기를 지정하여 axes 객체를 생성한다.
ax1 = fig.add_axes([0,0.5,0.4,0.4])
ax2 = fig.add_axes([0.5,0.5,0.4,0.4])
ax3 = fig.add_axes([0,0,0.4,0.4])
ax4 = fig.add_axes([0.5,0,0.4,0.4])
ax5 = fig.add_axes([0.3, 0.3, 0.3, 0.3])
# 3) axes에 그래프를 그린다.
ax1.plot(df1['x'], df1['y'], 'o')
ax2.plot(df2['x'], df2['y'], 'g^')
ax3.plot(df3['x'], df3['y'], 'rs')
ax4.plot(df4['x'], df4['y'], 'o', color = 'orange')
ax5.plot(df1['x'], df1['y'], 'o')
# 4) axes에 제목 추가
ax1.set_title('ax1')
ax2.set_title('ax2')
ax3.set_title('ax3')
ax4.set_title('ax4')
plt.show()
9.3 axes를 행,열로 쪼개어 그래프 그리기
- fig, ax = plt.subplots(nrows=행개수, ncols=열개수,figsize=(가로사이즈,세로사이즈))
- axes[행번호][열번호]로 각각의 위치에 그래프를 그려넣을 수 있음
- plt.subplots(sharex/sharey = True): 그래프들이 모두 같은 축을 공유하도록 설정할 수 있음
# 1) axes 객체를 행,열로 쪼개어 생성하기
# 3) 서브플롯간 축을 공유할 수 있다.
fig, ax = plt.subplots(nrows = 2, ncols = 2, figsize=(8, 6), sharex = True)
# 2) axes[행번호][열번호] 형태로 접근하여 그래프 그리기
ax[0][0].plot(df1['x'], df1['y'], 'o')
ax[0][1].plot(df2['x'], df2['y'], '^')
ax[1][0].plot(df3['x'], df3['y'], '*')
ax[1][1].plot(df4['x'], df4['y'], 'd')
# 4) 각 그래프에 제목 추가
ax[0][0].set_title('ax1')
ax[0][1].set_title('ax2')
ax[1][0].set_title('ax3')
ax[1][1].set_title('ax4')
# 4) 각 그래프에 그리드 추가
ax[0][0].grid(ls = ':')
ax[0][1].grid(ls = ':', color = 'pink')
ax[1][0].grid(ls = '--')
ax[1][1].grid(ls = ':', color = 'skyblue')
# 6) 그래프 전체 제목
fig.suptitle('Anscombe', size = 20)
# 7) 그래프 간격, 크기 최적화
fig.tight_layout()
소감 및 정리
그동안은 그래프 옵션을 잘 쓰지 않았는데 그래프를 다채롭게 꾸밀 수 있는 다양한 옵션들에 대해 많이 알게되었다. 또 이런 옵션들을 잘 사용하면 그래프를 통해 보여주고자 하는 의도를 더 쉽고, 편하게 전할 수 있겠다는 생각이 들어서 효과적인 그래프를 그리기 위한 방법들에 대해 더 고민해야겠다는 생각이 들었다.
조원분들과 그동안 배운 내용이나 데이터 분석에 관한 대화를 나누면서 더 다채로운 경험, 프로젝트를 해보고싶다는 생각도 들었고, 더 열심히 해야겠다는 마음을 다잡을 수 있었다.