AI & BigData/데이터분석 관련

Matplotlib 기초 정리

Tigercow.Door 2018. 6. 11. 15:42
Matplotlib_clear

안녕하세요. 문범우입니다.

이번 포스팅에서는 파이썬 기반 시각화 라이브러리인 matplotlib에 대해서 알아보도록 하겠습니다.


해당 내용은 flearning의 김길호님의 강의를 바탕으로 작성되었습니다.

https://www.flearning.net/courses/6


1. Matplotlib 이란?


matplotlib은 다양한 데이터를 많은 방법으로 도식화 할 수 있도록 하는 파이썬 라이브러리로써, 우리는 matplotlib의 pyplot을 이용하게 됩니다.

이는 mathworks에서 개발한 매트랩(MATLAB)과 비슷한 형태를 가지고 있습니다.

matplotlib을 이용하면 우리가 이전에 알아본 numpy나 pandas에서 사용되는 자료구조를 쉽게 시각화 할 수 있습니다.


matplotlib을 사용하기 위해서는 먼저 matplotlib을 설치하고 아래와 같이 import를 해주어야 합니다.


import matplotlib

import matplotlib.pyplot as plt


또한 jupyter notebook에서 그래프를 제대로 확인하기 위해서는 아래와 같은 매직 커맨드를 작성해주셔야 합니다.


%matplotlib inline


이러한 매직커맨드는 맨 뒤에 inline 이외에도 우리가 아래에서 사용하는 nbagg 등의 다양한 속성이 있습니다.


Matplotlib 기초

1. Matplotlib 이란?

In [11]:
import matplotlib
import matplotlib.pyplot as plt
%matplotlib nbagg
#위와 같은 것이 %로 시작하는 것을 jupyter notebook의 magic command라고 한다.
# %who는 변수명의 리스트를 보여주고 %magic 은 모든 매직명령어를 보여준다.
# 전체적인 magic 명령어에 대해서는 다음 블로그를 참고
# http://studymake.tistory.com/601
# matplotlib 을 jupyter notebook에서 사용할 때, plot의 이미지를 보여주기 위해 magic command를 사용하는데,
# 이때 우리가 사용하는 nbagg 이외에도 다음과 같은 요소를 사용할 수 있다.
# Available matplotlib backends: ['osx', 'qt4', 'qt5', 'gtk3', 'notebook', 'wx', 'qt', 'nbagg','gtk', 'tk', 'inline']
# 사용되는 명령어에 대한 차이점이 정리되어 있는 사이트는 따로 찾지 못했지만
# 각각에 대해서는 matplotlib의 공식문서에서 참고 할 수 있는듯 하며,
# 우리가 사용하는 nbagg에 대해서는 다음 링크에서 확인할 수 있다.
# https://matplotlib.org/users/prev_whats_new/whats_new_1.4.html#the-nbagg-backend
import numpy as np
import pandas as pd

2. Plot의 종류

Line plot 그리기

In [12]:
# Series를 통한 line plot 그리기
s = pd.Series(np.random.randn(10).cumsum(), index=np.arange(0, 100, 10))
s
Out[12]:
0    -0.722984
10   -1.830547
20   -0.592063
30   -1.320894
40   -1.849281
50   -1.570039
60   -3.052119
70   -2.698092
80   -2.722053
90   -2.735229
dtype: float64
In [13]:
# 위에서 정의한 s라는 시리즈에 대해서 line plot을 그리고 싶다면?
s.plot()
Out[13]:
<matplotlib.axes._subplots.AxesSubplot at 0x108ef0c88>

s 라는 Series에서의 index와 value를 통해 그래프가 그려졌다.

그래프 우측상단의 전원버튼을 누르기 전까지 우리는 해당 그래프를 interactive하게 조작할 수 있다.

In [14]:
# DataFrame을 통한 line plot 그리기
df = pd.DataFrame(np.random.randn(10, 4).cumsum(axis=0),
                  columns=["A", "B", "C", "D"],
                  index=np.arange(0, 100, 10))
df
Out[14]:
A B C D
0 -0.278464 1.680385 0.711803 -0.216933
10 -0.239848 2.527778 1.558551 1.006354
20 -2.112968 1.384759 2.648977 -0.124528
30 -2.461009 -0.023573 2.145466 -0.253936
40 -4.098926 -0.191797 1.583091 -1.285248
50 -2.224330 0.036316 -0.053839 0.045480
60 -4.346708 0.467878 0.877064 -1.018642
70 -5.083230 2.082973 2.360633 0.942955
80 -5.860602 4.372568 2.506778 0.312459
90 -4.651125 5.932881 1.437739 -1.382153
In [16]:
df.plot()
Out[16]:
<matplotlib.axes._subplots.AxesSubplot at 0x109df6710>
In [17]:
# 하나의 열에 대해서만 보고 싶다면?
df['B'].plot()
Out[17]:
<matplotlib.axes._subplots.AxesSubplot at 0x10a859b38>

Bar plot 그리기

In [18]:
s2 = pd.Series(np.random.rand(16), index=list("abcdefghijklmnop"))
s2
Out[18]:
a    0.571031
b    0.225421
c    0.210635
d    0.247162
e    0.850638
f    0.300911
g    0.485898
h    0.573721
i    0.223882
j    0.248352
k    0.163142
l    0.977120
m    0.615089
n    0.376035
o    0.618324
p    0.374877
dtype: float64
In [19]:
s2.plot(kind='bar')
Out[19]:
<matplotlib.axes._subplots.AxesSubplot at 0x10b26a208>
In [21]:
# 가로방향의 bar plot그리기
s2.plot(kind='barh')
Out[21]:
<matplotlib.axes._subplots.AxesSubplot at 0x10c6f0908>
In [22]:
df2 = pd.DataFrame(np.random.rand(6, 4), 
                   index=["one", "two", "three", "four", "five", "six"],
                   columns=pd.Index(["A", "B", "C", "D"], name="Genus"))
df2
Out[22]:
Genus A B C D
one 0.832213 0.165459 0.385868 0.300776
two 0.937578 0.576798 0.175512 0.690425
three 0.473119 0.690937 0.844016 0.542061
four 0.974779 0.911599 0.880104 0.155459
five 0.421689 0.168038 0.637749 0.181037
six 0.921647 0.069688 0.143649 0.033414
In [23]:
df2.plot(kind='bar')
Out[23]:
<matplotlib.axes._subplots.AxesSubplot at 0x10d17e7f0>
In [28]:
df2.plot(kind='barh', stacked=True)
Out[28]:
<matplotlib.axes._subplots.AxesSubplot at 0x10feab8d0>

위와 같이 Stacked 속성을 True로 설정하면, 하나의 인덱스에 대한 각 열의 값을 한줄로 쌓아서 나타내준다.

Histogram 그리기

In [26]:
# histogram은 index가 필요없다.
s3 = pd.Series(np.random.normal(0, 1, size=200))
s3
Out[26]:
0      0.702157
1      1.868464
2      0.245772
3     -1.763628
4      0.274251
5      0.592265
6      1.389987
7      0.014794
8      1.563205
9      1.282294
10     1.133853
11    -0.493625
12    -0.109863
13    -1.010361
14    -0.463374
15     1.689398
16     0.707700
17     0.229864
18     0.663653
19     1.508395
20    -0.134370
21    -1.263692
22    -0.077196
23    -0.030551
24     0.501011
25    -1.031409
26    -0.737499
27    -1.137995
28     0.249251
29     1.038868
         ...   
170   -0.086284
171   -2.438848
172    1.445287
173   -1.504384
174   -0.205834
175    1.001070
176   -1.703474
177    1.279574
178   -2.100881
179    0.063170
180    0.117487
181    0.424143
182   -0.464350
183   -1.692921
184    1.207365
185    1.094119
186    0.073894
187    0.583378
188   -0.534405
189    0.153943
190    1.256873
191   -0.004071
192    0.058366
193    0.670475
194    0.171067
195    0.973028
196    1.956217
197   -0.326276
198    1.579637
199    0.482489
Length: 200, dtype: float64
In [29]:
s3.hist()
Out[29]:
<matplotlib.axes._subplots.AxesSubplot at 0x10ffae2e8>

x 축의 구간 개수를 bin이라고 한다.

이를 직접 설정할 수도 있다.

In [30]:
s3.hist(bins=50)
Out[30]:
<matplotlib.axes._subplots.AxesSubplot at 0x1104cb978>
In [31]:
s3.hist(bins=100, normed=True)
# normed 속성을 True로 설정하면, 각 bin에 속하는 개수를 전체 개수로 나눈 비율, 즉 정규화 한 값을 bar의 높이로 사용하게 된다.
/Users/doorbw/anaconda3/envs/tensorflow/lib/python3.6/site-packages/matplotlib/axes/_axes.py:6462: UserWarning: The 'normed' kwarg is deprecated, and has been replaced by the 'density' kwarg.
  warnings.warn("The 'normed' kwarg is deprecated, and has been "
Out[31]:
<matplotlib.axes._subplots.AxesSubplot at 0x110f38780>

산점도(Scatter plot) 그리기

산점도의 경우에는 서로 다른 두 개의 독립변수에 대해 두 변수가 어떤 관계가 있는지 살펴보기 위해 사용된다.

In [33]:
x1 = np.random.normal(1, 1, size=(100, 1))
x2 = np.random.normal(-2, 4, size=(100, 1))
X = np.concatenate((x1, x2), axis=1)
X
Out[33]:
array([[ -0.3752975 ,  -4.69632177],
       [ -0.04698916,  -4.48810875],
       [  1.74717283,  -0.34868675],
       [  0.53977735,   5.98690306],
       [  2.19560272,  -0.53224326],
       [  1.85560112,  -5.63141534],
       [  0.28454018,   5.53604463],
       [  0.34086298,   0.82643556],
       [  1.32418947,  -1.10798781],
       [ -0.16026676,   0.91206102],
       [  0.62835028,  -2.305019  ],
       [  0.02386657,  -0.04939291],
       [  0.32775761,   0.8708874 ],
       [  1.69300678,   0.82030524],
       [  0.03639971,   5.83583861],
       [  1.19705596,  -5.40561955],
       [  1.07506972,  -7.52184686],
       [ -0.70722271,  -6.14603835],
       [  2.05616086, -10.26781395],
       [  1.92073538,  -3.64888168],
       [ -0.43836808,  -1.65559736],
       [  0.30273185,   2.71540738],
       [  0.23428242,  -2.22381865],
       [  0.92756753,   4.90967821],
       [  1.47754154,  -3.57039587],
       [ -0.09946106,  -2.09104225],
       [  0.06980543,  -5.83826948],
       [  0.20407917,   1.49699183],
       [  0.9469974 ,  -7.41344223],
       [  0.82017219,  -4.75638851],
       [  0.74925644,  -2.4836476 ],
       [  2.0299929 ,  -2.03680619],
       [  2.32047941,  -6.13066376],
       [  0.0725809 ,  -2.41709658],
       [  0.23294954,  -5.97183844],
       [  3.82856874,  -7.73628173],
       [  0.77614686,   2.74164276],
       [ -0.64519886,  -3.51080445],
       [  0.98211557,   0.83733643],
       [ -0.38228938,  -7.04380458],
       [  1.15663522,  -1.55617342],
       [  1.12848796,  -4.09505285],
       [  1.47230335,  -9.9819745 ],
       [  3.36852289,   2.12181043],
       [  1.42208933,   5.68460404],
       [  1.38192053,  -2.12166219],
       [  0.39637136,  -3.70043018],
       [  1.25874442,  -3.05953224],
       [  0.10108179,   4.30545156],
       [  1.76232585,   1.79031377],
       [  0.54102997,  -3.91951573],
       [  0.24426261,  -2.60376638],
       [ -0.71967917,  -3.00980386],
       [  1.32021563,   3.68697073],
       [  2.25463748,   0.16791218],
       [  1.04784925,  -7.41960297],
       [  1.80469277,  -2.59370479],
       [  2.27347659, -10.78401626],
       [  1.6646036 ,   6.23271327],
       [  2.21040715,  -7.8898875 ],
       [  0.61453812,  -2.96520709],
       [  1.96961373,  -4.1496854 ],
       [  1.14945552,  -0.78437461],
       [  0.27188607,  -4.31517004],
       [  1.41522569,  -1.10475445],
       [  2.1333174 ,  -5.34900055],
       [  1.80192353,  -3.91111824],
       [  0.18020554,  -5.63744833],
       [  0.51661052,   0.73262081],
       [  0.87181006,  -3.22024912],
       [  1.91354815,   0.45616527],
       [  1.28036579, -12.41369689],
       [  1.52346283,  -5.22911673],
       [  2.43157892,  -1.40468189],
       [  1.24274055,  -5.97985771],
       [  0.29690167,  -5.53013669],
       [  0.45719233,  -1.34191916],
       [  1.09305251,   0.10975815],
       [  0.79708809,  -0.77606227],
       [  1.04444832,  -0.54505714],
       [  0.73797347,   0.21941888],
       [  0.07154705,  -0.99455787],
       [  1.97923968,   1.13446246],
       [  0.11196706,  -1.55174951],
       [  2.24508672,  -1.43301228],
       [  1.68657928,   6.35364726],
       [ -0.36898846,   1.38227227],
       [  0.3069036 ,  -1.68316641],
       [  2.02672646,  -5.75989468],
       [  1.27195767,  -6.9290835 ],
       [  0.48212216,  -1.47965137],
       [ -1.12937566,   0.07733721],
       [  1.70834259,  -2.9275322 ],
       [  2.65089294,   1.22713735],
       [  1.1471613 ,  -1.51379151],
       [  0.8905951 ,  -3.65772848],
       [  1.34541854, -10.66228373],
       [  0.83378688,  -6.00832702],
       [  1.02315838,   4.00222819],
       [  0.33959563,   4.49335211]])
In [34]:
df3 = pd.DataFrame(X, columns=["x1", "x2"])
df3
Out[34]:
x1 x2
0 -0.375297 -4.696322
1 -0.046989 -4.488109
2 1.747173 -0.348687
3 0.539777 5.986903
4 2.195603 -0.532243
5 1.855601 -5.631415
6 0.284540 5.536045
7 0.340863 0.826436
8 1.324189 -1.107988
9 -0.160267 0.912061
10 0.628350 -2.305019
11 0.023867 -0.049393
12 0.327758 0.870887
13 1.693007 0.820305
14 0.036400 5.835839
15 1.197056 -5.405620
16 1.075070 -7.521847
17 -0.707223 -6.146038
18 2.056161 -10.267814
19 1.920735 -3.648882
20 -0.438368 -1.655597
21 0.302732 2.715407
22 0.234282 -2.223819
23 0.927568 4.909678
24 1.477542 -3.570396
25 -0.099461 -2.091042
26 0.069805 -5.838269
27 0.204079 1.496992
28 0.946997 -7.413442
29 0.820172 -4.756389
... ... ...
70 1.913548 0.456165
71 1.280366 -12.413697
72 1.523463 -5.229117
73 2.431579 -1.404682
74 1.242741 -5.979858
75 0.296902 -5.530137
76 0.457192 -1.341919
77 1.093053 0.109758
78 0.797088 -0.776062
79 1.044448 -0.545057
80 0.737973 0.219419
81 0.071547 -0.994558
82 1.979240 1.134462
83 0.111967 -1.551750
84 2.245087 -1.433012
85 1.686579 6.353647
86 -0.368988 1.382272
87 0.306904 -1.683166
88 2.026726 -5.759895
89 1.271958 -6.929084
90 0.482122 -1.479651
91 -1.129376 0.077337
92 1.708343 -2.927532
93 2.650893 1.227137
94 1.147161 -1.513792
95 0.890595 -3.657728
96 1.345419 -10.662284
97 0.833787 -6.008327
98 1.023158 4.002228
99 0.339596 4.493352

100 rows × 2 columns

In [36]:
plt.scatter(df3['x1'], df3['x2']) # x1이 x축, x2가 y축
Out[36]:
<matplotlib.collections.PathCollection at 0x11257b080>

3. Plot 모양 변형하기

In [50]:
fig = plt.figure()
# 비어있는 figure가 생성된다.
In [39]:
# subplot 추가하기, add_subplot 에는 총 3가지 인자가 들어간다.
In [51]:
ax1 = fig.add_subplot(2, 2, 1)
In [52]:
# 첫번째 숫자와 두번째 숫자 : 우리가 figure를 어떤 크기로 나눌지에 대한 값이다. 즉 위의 같은 경우는 2,2 이므로 우리의 figure를 2x2로 나눈다는 뜻.
# 세번째 숫자 : 첫번째, 두번째 숫자로 나눈 figure에서 좌측상단으로 우측방향으로 숫자가 붙는다. 이때 우리가 add하고자 하는 subplot이 몇번째에 들어가는지를 나타낸다.
# 즉, 위와 같은 경우 figure는 다음과 같이 나누어진다.
# 1  2
# 3  4
# 이때 우리는 1위치에 subplot을 추가하고 해당 subplot을 ax1이라는 변수로 반환받는다.
In [53]:
ax2 = fig.add_subplot(2,2,2)
In [54]:
ax3 = fig.add_subplot(2,2,3)
In [55]:
plt.plot(np.random.randn(50).cumsum())
# 위치를 지정하지 않고 plot을 그리니 맨마지막에 그림이 그려진다.
# figure에 추가된 subplot상 맨 마지막에 위치한 곳에 그려지는 것이 아니라, 제일 마지막에 추가한 subplot에 그려진다.
# 2 -> 3 -> 1 순으로 subplot을 추가하여 테스트 해보면 1번 요소에 그려진다.
Out[55]:
[<matplotlib.lines.Line2D at 0x116378160>]
In [56]:
plt.plot(np.random.randn(200).cumsum())
# 강의에서는 한번더 위치 지정 없이 그리면 그 전의 요소에 그려진다고 했는데,
# 실제로 진행해보면 그냥 위의 것과 똑같이 제일 마지막에 추가한 subplot에 중복되서 그려진다.
Out[56]:
[<matplotlib.lines.Line2D at 0x116384278>]
In [57]:
# 그럼 우리가 원하는 위치에 그림을 그리기 위해서는?
# 위에서 add_subplot 을 할때 변수명을 지정하여 반환값을 받았다.
# 해당 변수를 통해 plot을 그리면 된다.
ax1.hist(np.random.randn(100), bins = 20) # bins는 x축 bar의 개수
Out[57]:
(array([ 2.,  1.,  2.,  1.,  4.,  4.,  6.,  9.,  6.,  9., 16.,  6.,  9.,
        10.,  4.,  7.,  2.,  0.,  0.,  2.]),
 array([-2.65952998, -2.40690555, -2.15428112, -1.9016567 , -1.64903227,
        -1.39640784, -1.14378341, -0.89115898, -0.63853456, -0.38591013,
        -0.1332857 ,  0.11933873,  0.37196316,  0.62458759,  0.87721201,
         1.12983644,  1.38246087,  1.6350853 ,  1.88770973,  2.14033415,
         2.39295858]),
 <a list of 20 Patch objects>)
In [58]:
ax2.scatter(np.arange(30), np.arange(30) + 3 * np.random.randn(30))
Out[58]:
<matplotlib.collections.PathCollection at 0x1162d7c18>
In [59]:
# 또 다른 방법
fig, axes = plt.subplots(2,3)
# 위와 같이 만들면 2x3 subplot들을 가지는 figure를 만드는 것
# 이때 반환되는 값은 2개로써, figrue 자체와, 축
In [49]:
# 반환받은 axes에는 우리가 위에서 설정한 크기와 같은 shape의 리스트로 각 요소에는 subplot 객체가 들어있다.
axes
Out[49]:
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x115212160>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x115231748>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x115255cf8>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x1152873c8>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x1152afa90>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x1152e2278>]],
      dtype=object)

3-1. Plot 꾸미기

In [60]:
plt.plot(np.random.randn(50), color = 'g', marker='o', linestyle='--')
Out[60]:
[<matplotlib.lines.Line2D at 0x11654deb8>]

color

값 색상

"b" blue

"g" green

"r" red

"c" cyan

"m" magenta

"y" yellow

"k" black

"w" white

marker

값 마킹

"." point

"," pixel

"o" circle

"v" triangle_down

"^" triangle_up

"<" triangle_left

">" triangle_right

"8" octagon

"s" square

"p" pentagon

"*" star

"h" hexagon

"+" plus

"x" x

"D" diamond

line style

값 라인 스타일

"-" solid line

"--" dashed line

"-." dash-dotted line

":" dotted line

"None" draw nothing

In [63]:
# 굳이 각각에 대해서 언급해주지 않고, 아래와 같이 연속적으로 나타내줘도 된다.
plt.plot(np.random.randn(30), 'k.-')
Out[63]:
[<matplotlib.lines.Line2D at 0x116aaecf8>]
In [69]:
fig, axes = plt.subplots(2,1)
In [70]:
data = pd.Series(np.random.rand(16), index=list('abcdefghijklmnop'))
In [71]:
data.plot(kind='bar', ax=axes[0], color='k', alpha=0.7) #plot 함수를 그릴때, figure에서 원하는 위치를 지정하기 위해 ax 속성을 사용
Out[71]:
<matplotlib.axes._subplots.AxesSubplot at 0x117ab1c50>
In [72]:
data.plot(kind='barh', ax=axes[1], color='g', alpha=0.3)
Out[72]:
<matplotlib.axes._subplots.AxesSubplot at 0x1184960b8>

우리가 만들 plot의 눈금, 레이블, 범위 등을 지정 및 수정할 수 있다.

In [73]:
fig = plt.figure()
In [74]:
ax = fig.add_subplot(1,1,1)
In [75]:
ax.plot(np.random.randn(1000).cumsum())
Out[75]:
[<matplotlib.lines.Line2D at 0x119940320>]
In [76]:
# 이때 그래프에서 나타내는 눈금을 tick이라고 한다.
# 즉, 위의 그래프의 x tick은 200이고 y tick은 10이다.
In [77]:
ax.set_xticks([0, 250, 500, 750, 1000])
Out[77]:
[<matplotlib.axis.XTick at 0x11940ac88>,
 <matplotlib.axis.XTick at 0x11940a5c0>,
 <matplotlib.axis.XTick at 0x117ab18d0>,
 <matplotlib.axis.XTick at 0x119926a90>,
 <matplotlib.axis.XTick at 0x1199321d0>]
In [78]:
# 눈금을 문자로 하기 위해서는?
labels = ax.set_xticklabels(['one', 'two', 'three', 'four', 'five'], rotation = 30, fontsize='small')
In [79]:
# 제목 입력하기
ax.set_title('random walk plot')
Out[79]:
Text(0.5,1,'random walk plot')
In [80]:
# 라벨 입력하기
ax.set_xlabel('Stages')
ax.set_ylabel('Values')
Out[80]:
Text(70.8194,0.5,'Values')
In [81]:
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
In [82]:
ax.plot(np.random.randn(1000).cumsum(), 'k', label='one')
ax.plot(np.random.randn(1000).cumsum(), 'b--', label='two')
ax.plot(np.random.randn(1000).cumsum(), 'r.', label='three')
Out[82]:
[<matplotlib.lines.Line2D at 0x119939da0>]
In [83]:
# 범례 표시하기
ax.legend(loc='best')
# loc는 범례가 위치할 곳을 의미한다. best를 주게 되면 현재 그래프에서 최적의 위치를 자동으로 찾는다.
Out[83]:
<matplotlib.legend.Legend at 0x119f4f550>

x축 범위 및 y축 범위 수정하기

In [84]:
ax.get_xlim()
# 현재 그래프의 x축 범위를 가져온다.
Out[84]:
(-49.95, 1048.95)
In [85]:
# 이를 변경하려면,
ax.set_xlim([100,900])
Out[85]:
(100, 900)
In [86]:
ax.set_ylim([-100,100])
Out[86]:
(-100, 100)

3. Matplotlib을 이용한 데이터시각화 맛보기

In [87]:
battles = pd.read_csv('game-of-thrones/battles.csv', sep=',')
deaths = pd.read_csv('game-of-thrones/character-deaths.csv', sep=',')
In [88]:
battles.head()
Out[88]:
name year battle_number attacker_king defender_king attacker_1 attacker_2 attacker_3 attacker_4 defender_1 ... major_death major_capture attacker_size defender_size attacker_commander defender_commander summer location region note
0 Battle of the Golden Tooth 298 1 Joffrey/Tommen Baratheon Robb Stark Lannister NaN NaN NaN Tully ... 1.0 0.0 15000.0 4000.0 Jaime Lannister Clement Piper, Vance 1.0 Golden Tooth The Westerlands NaN
1 Battle at the Mummer's Ford 298 2 Joffrey/Tommen Baratheon Robb Stark Lannister NaN NaN NaN Baratheon ... 1.0 0.0 NaN 120.0 Gregor Clegane Beric Dondarrion 1.0 Mummer's Ford The Riverlands NaN
2 Battle of Riverrun 298 3 Joffrey/Tommen Baratheon Robb Stark Lannister NaN NaN NaN Tully ... 0.0 1.0 15000.0 10000.0 Jaime Lannister, Andros Brax Edmure Tully, Tytos Blackwood 1.0 Riverrun The Riverlands NaN
3 Battle of the Green Fork 298 4 Robb Stark Joffrey/Tommen Baratheon Stark NaN NaN NaN Lannister ... 1.0 1.0 18000.0 20000.0 Roose Bolton, Wylis Manderly, Medger Cerwyn, H... Tywin Lannister, Gregor Clegane, Kevan Lannist... 1.0 Green Fork The Riverlands NaN
4 Battle of the Whispering Wood 298 5 Robb Stark Joffrey/Tommen Baratheon Stark Tully NaN NaN Lannister ... 1.0 1.0 1875.0 6000.0 Robb Stark, Brynden Tully Jaime Lannister 1.0 Whispering Wood The Riverlands NaN

5 rows × 25 columns

In [89]:
battles.columns
Out[89]:
Index(['name', 'year', 'battle_number', 'attacker_king', 'defender_king',
       'attacker_1', 'attacker_2', 'attacker_3', 'attacker_4', 'defender_1',
       'defender_2', 'defender_3', 'defender_4', 'attacker_outcome',
       'battle_type', 'major_death', 'major_capture', 'attacker_size',
       'defender_size', 'attacker_commander', 'defender_commander', 'summer',
       'location', 'region', 'note'],
      dtype='object')
In [90]:
battles.shape
Out[90]:
(38, 25)
In [91]:
deaths.shape
Out[91]:
(917, 13)
In [92]:
deaths.columns
Out[92]:
Index(['Name', 'Allegiances', 'Death Year', 'Book of Death', 'Death Chapter',
       'Book Intro Chapter', 'Gender', 'Nobility', 'GoT', 'CoK', 'SoS', 'FfC',
       'DwD'],
      dtype='object')
In [93]:
deaths.head()
Out[93]:
Name Allegiances Death Year Book of Death Death Chapter Book Intro Chapter Gender Nobility GoT CoK SoS FfC DwD
0 Addam Marbrand Lannister NaN NaN NaN 56.0 1 1 1 1 1 1 0
1 Aegon Frey (Jinglebell) None 299.0 3.0 51.0 49.0 1 1 0 0 1 0 0
2 Aegon Targaryen House Targaryen NaN NaN NaN 5.0 1 1 0 0 0 0 1
3 Adrack Humble House Greyjoy 300.0 5.0 20.0 20.0 1 1 0 0 0 0 1
4 Aemon Costayne Lannister NaN NaN NaN NaN 1 1 0 0 1 0 0
In [95]:
book_nums_to_death_count = deaths['Book of Death'].value_counts().sort_index()
book_nums_to_death_count
Out[95]:
1.0    49
2.0    73
3.0    97
4.0    27
5.0    61
Name: Book of Death, dtype: int64
In [96]:
ax1 = book_nums_to_death_count.plot(color = 'k', marker='o', linestyle='--')
In [97]:
# 모양 가다듬기
ax1.set_xticks(np.arange(1,6))
Out[97]:
[<matplotlib.axis.XTick at 0x117aa3048>,
 <matplotlib.axis.XTick at 0x117a6cb70>,
 <matplotlib.axis.XTick at 0x11a9e1f98>,
 <matplotlib.axis.XTick at 0x11a9e9630>,
 <matplotlib.axis.XTick at 0x11a9e9d68>]
In [98]:
ax1.set_xlim([0,6])
ax1.set_ylim([0,120])
Out[98]:
(0, 120)
In [99]:
battles = battles.set_index(['name'])
In [100]:
battles.head()
Out[100]:
year battle_number attacker_king defender_king attacker_1 attacker_2 attacker_3 attacker_4 defender_1 defender_2 ... major_death major_capture attacker_size defender_size attacker_commander defender_commander summer location region note
name
Battle of the Golden Tooth 298 1 Joffrey/Tommen Baratheon Robb Stark Lannister NaN NaN NaN Tully NaN ... 1.0 0.0 15000.0 4000.0 Jaime Lannister Clement Piper, Vance 1.0 Golden Tooth The Westerlands NaN
Battle at the Mummer's Ford 298 2 Joffrey/Tommen Baratheon Robb Stark Lannister NaN NaN NaN Baratheon NaN ... 1.0 0.0 NaN 120.0 Gregor Clegane Beric Dondarrion 1.0 Mummer's Ford The Riverlands NaN
Battle of Riverrun 298 3 Joffrey/Tommen Baratheon Robb Stark Lannister NaN NaN NaN Tully NaN ... 0.0 1.0 15000.0 10000.0 Jaime Lannister, Andros Brax Edmure Tully, Tytos Blackwood 1.0 Riverrun The Riverlands NaN
Battle of the Green Fork 298 4 Robb Stark Joffrey/Tommen Baratheon Stark NaN NaN NaN Lannister NaN ... 1.0 1.0 18000.0 20000.0 Roose Bolton, Wylis Manderly, Medger Cerwyn, H... Tywin Lannister, Gregor Clegane, Kevan Lannist... 1.0 Green Fork The Riverlands NaN
Battle of the Whispering Wood 298 5 Robb Stark Joffrey/Tommen Baratheon Stark Tully NaN NaN Lannister NaN ... 1.0 1.0 1875.0 6000.0 Robb Stark, Brynden Tully Jaime Lannister 1.0 Whispering Wood The Riverlands NaN

5 rows × 24 columns

In [101]:
large_battle_mask = battles['attacker_size'] + battles['defender_size'] > 10000
In [102]:
large_battles = battles.loc[large_battle_mask, ['attacker_size', 'defender_size']]
In [103]:
large_battles.shape
Out[103]:
(10, 2)
In [104]:
large_battles
Out[104]:
attacker_size defender_size
name
Battle of the Golden Tooth 15000.0 4000.0
Battle of Riverrun 15000.0 10000.0
Battle of the Green Fork 18000.0 20000.0
Battle of the Camps 6000.0 12625.0
Battle of Oxcross 6000.0 10000.0
Siege of Storm's End 5000.0 20000.0
Battle of the Fords 20000.0 10000.0
Battle of the Blackwater 21000.0 7250.0
Battle of Castle Black 100000.0 1240.0
Siege of Winterfell 5000.0 8000.0
In [105]:
ax2 = large_battles.plot(kind='barh', stacked=True, fontsize=8)
In [106]:
large_battles['attacker_pcts'] = large_battles['attacker_size'] / (large_battles['attacker_size'] + large_battles['defender_size'])
In [107]:
large_battles['defender_pcts'] = large_battles['defender_size'] / (large_battles['attacker_size'] + large_battles['defender_size'])
In [108]:
large_battles
Out[108]:
attacker_size defender_size attacker_pcts defender_pcts
name
Battle of the Golden Tooth 15000.0 4000.0 0.789474 0.210526
Battle of Riverrun 15000.0 10000.0 0.600000 0.400000
Battle of the Green Fork 18000.0 20000.0 0.473684 0.526316
Battle of the Camps 6000.0 12625.0 0.322148 0.677852
Battle of Oxcross 6000.0 10000.0 0.375000 0.625000
Siege of Storm's End 5000.0 20000.0 0.200000 0.800000
Battle of the Fords 20000.0 10000.0 0.666667 0.333333
Battle of the Blackwater 21000.0 7250.0 0.743363 0.256637
Battle of Castle Black 100000.0 1240.0 0.987752 0.012248
Siege of Winterfell 5000.0 8000.0 0.384615 0.615385
In [124]:
ax3 = large_battles[['attacker_pcts', 'defender_pcts']].plot(kind='barh', stacked=True, fontsize=8)
In [125]:
battles
Out[125]:
year battle_number attacker_king defender_king attacker_1 attacker_2 attacker_3 attacker_4 defender_1 defender_2 ... major_death major_capture attacker_size defender_size attacker_commander defender_commander summer location region note
name
Battle of the Golden Tooth 298 1 Joffrey/Tommen Baratheon Robb Stark Lannister NaN NaN NaN Tully NaN ... 1.0 0.0 15000.0 4000.0 Jaime Lannister Clement Piper, Vance 1.0 Golden Tooth The Westerlands NaN
Battle at the Mummer's Ford 298 2 Joffrey/Tommen Baratheon Robb Stark Lannister NaN NaN NaN Baratheon NaN ... 1.0 0.0 NaN 120.0 Gregor Clegane Beric Dondarrion 1.0 Mummer's Ford The Riverlands NaN
Battle of Riverrun 298 3 Joffrey/Tommen Baratheon Robb Stark Lannister NaN NaN NaN Tully NaN ... 0.0 1.0 15000.0 10000.0 Jaime Lannister, Andros Brax Edmure Tully, Tytos Blackwood 1.0 Riverrun The Riverlands NaN
Battle of the Green Fork 298 4 Robb Stark Joffrey/Tommen Baratheon Stark NaN NaN NaN Lannister NaN ... 1.0 1.0 18000.0 20000.0 Roose Bolton, Wylis Manderly, Medger Cerwyn, H... Tywin Lannister, Gregor Clegane, Kevan Lannist... 1.0 Green Fork The Riverlands NaN
Battle of the Whispering Wood 298 5 Robb Stark Joffrey/Tommen Baratheon Stark Tully NaN NaN Lannister NaN ... 1.0 1.0 1875.0 6000.0 Robb Stark, Brynden Tully Jaime Lannister 1.0 Whispering Wood The Riverlands NaN
Battle of the Camps 298 6 Robb Stark Joffrey/Tommen Baratheon Stark Tully NaN NaN Lannister NaN ... 0.0 0.0 6000.0 12625.0 Robb Stark, Tytos Blackwood, Brynden Tully Lord Andros Brax, Forley Prester 1.0 Riverrun The Riverlands NaN
Sack of Darry 298 7 Joffrey/Tommen Baratheon Robb Stark Lannister NaN NaN NaN Darry NaN ... 0.0 0.0 NaN NaN Gregor Clegane Lyman Darry 1.0 Darry The Riverlands NaN
Battle of Moat Cailin 299 8 Balon/Euron Greyjoy Robb Stark Greyjoy NaN NaN NaN Stark NaN ... 0.0 0.0 NaN NaN Victarion Greyjoy NaN 1.0 Moat Cailin The North NaN
Battle of Deepwood Motte 299 9 Balon/Euron Greyjoy Robb Stark Greyjoy NaN NaN NaN Stark NaN ... 0.0 0.0 1000.0 NaN Asha Greyjoy NaN 1.0 Deepwood Motte The North NaN
Battle of the Stony Shore 299 10 Balon/Euron Greyjoy Robb Stark Greyjoy NaN NaN NaN Stark NaN ... 0.0 0.0 264.0 NaN Theon Greyjoy NaN 1.0 Stony Shore The North Greyjoy's troop number based on the Battle of ...
Battle of Torrhen's Square 299 11 Robb Stark Balon/Euron Greyjoy Stark NaN NaN NaN Greyjoy NaN ... 0.0 0.0 244.0 900.0 Rodrik Cassel, Cley Cerwyn Dagmer Cleftjaw 1.0 Torrhen's Square The North Greyjoy's troop number comes from the 264 esti...
Battle of Winterfell 299 12 Balon/Euron Greyjoy Robb Stark Greyjoy NaN NaN NaN Stark NaN ... 0.0 1.0 20.0 NaN Theon Greyjoy Bran Stark 1.0 Winterfell The North It isn't mentioned how many Stark men are left...
Sack of Torrhen's Square 299 13 Balon/Euron Greyjoy Balon/Euron Greyjoy Greyjoy NaN NaN NaN Stark NaN ... 0.0 1.0 NaN NaN Dagmer Cleftjaw NaN 1.0 Torrhen's Square The North NaN
Sack of Winterfell 299 14 Joffrey/Tommen Baratheon Robb Stark Bolton Greyjoy NaN NaN Stark NaN ... 1.0 0.0 618.0 2000.0 Ramsay Snow, Theon Greyjoy Rodrik Cassel, Cley Cerwyn, Leobald Tallhart 1.0 Winterfell The North Since House Bolton betrays the Starks for Hous...
Battle of Oxcross 299 15 Robb Stark Joffrey/Tommen Baratheon Stark Tully NaN NaN Lannister NaN ... 1.0 1.0 6000.0 10000.0 Robb Stark, Brynden Tully Stafford Lannister, Roland Crakehall, Antario ... 1.0 Oxcross The Westerlands NaN
Siege of Storm's End 299 16 Stannis Baratheon Renly Baratheon Baratheon NaN NaN NaN Baratheon NaN ... 1.0 0.0 5000.0 20000.0 Stannis Baratheon, Davos Seaworth Renly Baratheon, Cortnay Penrose, Loras Tyrell... 1.0 Storm's End The Stormlands NaN
Battle of the Fords 299 17 Joffrey/Tommen Baratheon Robb Stark Lannister NaN NaN NaN Tully NaN ... 0.0 0.0 20000.0 10000.0 Tywin Lannister, Flement Brax, Gregor Clegane,... Edmure Tully, Jason Mallister, Karyl Vance 1.0 Red Fork The Riverlands NaN
Sack of Harrenhal 299 18 Robb Stark Joffrey/Tommen Baratheon Stark NaN NaN NaN Lannister NaN ... 1.0 0.0 100.0 100.0 Roose Bolton, Vargo Hoat, Robett Glover Amory Lorch 1.0 Harrenhal The Riverlands NaN
Battle of the Crag 299 19 Robb Stark Joffrey/Tommen Baratheon Stark NaN NaN NaN Lannister NaN ... 0.0 0.0 6000.0 NaN Robb Stark, Smalljon Umber, Black Walder Frey Rolph Spicer 1.0 Crag The Westerlands NaN
Battle of the Blackwater 299 20 Stannis Baratheon Joffrey/Tommen Baratheon Baratheon NaN NaN NaN Lannister NaN ... 1.0 1.0 21000.0 7250.0 Stannis Baratheon, Imry Florent, Guyard Morrig... Tyrion Lannister, Jacelyn Bywater, Sandor Cleg... 1.0 King's Landing The Crownlands NaN
Siege of Darry 299 21 Robb Stark Joffrey/Tommen Baratheon Darry NaN NaN NaN Lannister NaN ... 0.0 0.0 NaN NaN Helman Tallhart NaN 1.0 Darry The Riverlands NaN
Battle of Duskendale 299 22 Robb Stark Joffrey/Tommen Baratheon Stark NaN NaN NaN Lannister NaN ... 1.0 0.0 3000.0 NaN Robertt Glover, Helman Tallhart Randyll Tarly, Gregor Clegane 1.0 Duskendale The Crownlands NaN
Battle of the Burning Septry 299 23 NaN NaN Brotherhood without Banners NaN NaN NaN Brave Companions NaN ... 0.0 0.0 NaN NaN NaN NaN 1.0 NaN The Riverlands NaN
Battle of the Ruby Ford 299 24 Joffrey/Tommen Baratheon Robb Stark Lannister NaN NaN NaN Stark NaN ... 0.0 0.0 NaN 6000.0 Gregor Clegane Roose Bolton, Wylis Manderly NaN Ruby Ford The Riverlands NaN
Retaking of Harrenhal 299 25 Joffrey/Tommen Baratheon NaN Lannister NaN NaN NaN Brave Companions NaN ... 1.0 0.0 NaN NaN Gregor Clegane Vargo Hoat 1.0 Harrenhal The Riverlands NaN
The Red Wedding 299 26 Joffrey/Tommen Baratheon Robb Stark Frey Bolton NaN NaN Stark NaN ... 1.0 1.0 3500.0 3500.0 Walder Frey, Roose Bolton, Walder Rivers Robb Stark 1.0 The Twins The Riverlands This observation refers to the battle against ...
Siege of Seagard 299 27 Robb Stark Joffrey/Tommen Baratheon Frey NaN NaN NaN Mallister NaN ... 0.0 1.0 NaN NaN Walder Frey Jason Mallister 1.0 Seagard The Riverlands NaN
Battle of Castle Black 300 28 Stannis Baratheon Mance Rayder Free folk Thenns Giants NaN Night's Watch Baratheon ... 1.0 1.0 100000.0 1240.0 Mance Rayder, Tormund Giantsbane, Harma Dogshe... Stannis Baratheon, Jon Snow, Donal Noye, Cotte... 0.0 Castle Black Beyond the Wall NaN
Fall of Moat Cailin 300 29 Joffrey/Tommen Baratheon Balon/Euron Greyjoy Bolton NaN NaN NaN Greyjoy NaN ... 0.0 0.0 NaN NaN Ramsey Bolton NaN 0.0 Moat Cailin The North NaN
Sack of Saltpans 300 30 NaN NaN Brave Companions NaN NaN NaN NaN NaN ... 0.0 0.0 NaN NaN Rorge NaN 0.0 Saltpans The Riverlands NaN
Retaking of Deepwood Motte 300 31 Stannis Baratheon Balon/Euron Greyjoy Baratheon Karstark Mormont Glover Greyjoy NaN ... 0.0 0.0 4500.0 200.0 Stannis Baratheon, Alysane Mormot Asha Greyjoy 0.0 Deepwood Motte The North NaN
Battle of the Shield Islands 300 32 Balon/Euron Greyjoy Joffrey/Tommen Baratheon Greyjoy NaN NaN NaN Tyrell NaN ... 0.0 0.0 NaN NaN Euron Greyjoy, Victarion Greyjoy NaN 0.0 Shield Islands The Reach NaN
Invasion of Ryamsport, Vinetown, and Starfish Harbor 300 33 Balon/Euron Greyjoy Joffrey/Tommen Baratheon Greyjoy NaN NaN NaN Tyrell NaN ... 0.0 0.0 NaN NaN Euron Greyjoy, Victarion Greyjoy NaN 0.0 Ryamsport, Vinetown, Starfish Harbor The Reach NaN
Second Seige of Storm's End 300 34 Joffrey/Tommen Baratheon Stannis Baratheon Baratheon NaN NaN NaN Baratheon NaN ... 0.0 0.0 NaN 200.0 Mace Tyrell, Mathis Rowan Gilbert Farring 0.0 Storm's End The Stormlands NaN
Siege of Dragonstone 300 35 Joffrey/Tommen Baratheon Stannis Baratheon Baratheon NaN NaN NaN Baratheon NaN ... 0.0 0.0 2000.0 NaN Loras Tyrell, Raxter Redwyne Rolland Storm 0.0 Dragonstone The Stormlands NaN
Siege of Riverrun 300 36 Joffrey/Tommen Baratheon Robb Stark Lannister Frey NaN NaN Tully NaN ... 0.0 0.0 3000.0 NaN Daven Lannister, Ryman Fey, Jaime Lannister Brynden Tully 0.0 Riverrun The Riverlands NaN
Siege of Raventree 300 37 Joffrey/Tommen Baratheon Robb Stark Bracken Lannister NaN NaN Blackwood NaN ... 0.0 1.0 1500.0 NaN Jonos Bracken, Jaime Lannister Tytos Blackwood 0.0 Raventree The Riverlands NaN
Siege of Winterfell 300 38 Stannis Baratheon Joffrey/Tommen Baratheon Baratheon Karstark Mormont Glover Bolton Frey ... NaN NaN 5000.0 8000.0 Stannis Baratheon Roose Bolton 0.0 Winterfell The North NaN

38 rows × 24 columns

In [126]:
col_names = battles.columns[4:12]
col_names
Out[126]:
Index(['attacker_1', 'attacker_2', 'attacker_3', 'attacker_4', 'defender_1',
       'defender_2', 'defender_3', 'defender_4'],
      dtype='object')
In [127]:
# 각 가문이 얼마나 전투에 참여했는지 보기위해 먼저 col_names를 가져왔다.
# 이에 대해서 unique 처리를 하려고하는데, 이때 NaN값이 있으면 오류가 발생하므로 이를 먼저 처리한다.
# NaN을 None이라는 문자열로 대체할 것
house_names = battles[col_names].fillna("None").values
In [128]:
house_names[:5]
Out[128]:
array([['Lannister', 'None', 'None', 'None', 'Tully', 'None', 'None',
        'None'],
       ['Lannister', 'None', 'None', 'None', 'Baratheon', 'None', 'None',
        'None'],
       ['Lannister', 'None', 'None', 'None', 'Tully', 'None', 'None',
        'None'],
       ['Stark', 'None', 'None', 'None', 'Lannister', 'None', 'None',
        'None'],
       ['Stark', 'Tully', 'None', 'None', 'Lannister', 'None', 'None',
        'None']], dtype=object)
In [129]:
house_names = np.unique(house_names)
house_names
Out[129]:
array(['Baratheon', 'Blackwood', 'Bolton', 'Bracken', 'Brave Companions',
       'Brotherhood without Banners', 'Darry', 'Free folk', 'Frey',
       'Giants', 'Glover', 'Greyjoy', 'Karstark', 'Lannister',
       'Mallister', 'Mormont', "Night's Watch", 'None', 'Stark', 'Thenns',
       'Tully', 'Tyrell'], dtype=object)
In [130]:
house_names = house_names[house_names != 'None']
house_names
Out[130]:
array(['Baratheon', 'Blackwood', 'Bolton', 'Bracken', 'Brave Companions',
       'Brotherhood without Banners', 'Darry', 'Free folk', 'Frey',
       'Giants', 'Glover', 'Greyjoy', 'Karstark', 'Lannister',
       'Mallister', 'Mormont', "Night's Watch", 'Stark', 'Thenns',
       'Tully', 'Tyrell'], dtype=object)
In [131]:
houses_to_battle_counts = pd.Series(0, index=house_names)
houses_to_battle_counts
Out[131]:
Baratheon                      0
Blackwood                      0
Bolton                         0
Bracken                        0
Brave Companions               0
Brotherhood without Banners    0
Darry                          0
Free folk                      0
Frey                           0
Giants                         0
Glover                         0
Greyjoy                        0
Karstark                       0
Lannister                      0
Mallister                      0
Mormont                        0
Night's Watch                  0
Stark                          0
Thenns                         0
Tully                          0
Tyrell                         0
dtype: int64
In [135]:
for col in col_names:
    houses_to_battle_counts = houses_to_battle_counts.add(battles[col].value_counts(), fill_value = 0)
In [136]:
houses_to_battle_counts
Out[136]:
Baratheon                      22.0
Blackwood                       2.0
Bolton                          8.0
Bracken                         2.0
Brave Companions                6.0
Brotherhood without Banners     2.0
Darry                           4.0
Free folk                       2.0
Frey                            8.0
Giants                          2.0
Glover                          4.0
Greyjoy                        22.0
Karstark                        4.0
Lannister                      36.0
Mallister                       2.0
Mormont                         4.0
Night's Watch                   2.0
Stark                          32.0
Thenns                          2.0
Tully                          14.0
Tyrell                          4.0
dtype: float64
In [137]:
ax4 = houses_to_battle_counts.hist(bins=10)
In [123]:
ax4
Out[123]:
<matplotlib.axes._subplots.AxesSubplot at 0x10231c710>


728x90