Skip to content

Latest commit

 

History

History
403 lines (278 loc) · 14.2 KB

File metadata and controls

403 lines (278 loc) · 14.2 KB

Matplotlib 소개: 그래프 그리기

Matplotlib는 Python에서 그래프를 그릴 때 사용하는 대표적인 라이브러리입니다. Pandas와 기본적으로 통합되어 있는 라이브러리이기도 합니다. Pandas에서 SeriesDataFrame 의 메소드로 제공되는 plot() 함수는 기본적으로 matplotlib을 사용해서 그래프를 그립니다. 때문에 많은 기능들이 상호 호환됩니다.

여기서는 순수한 matplotlib을 사용해서 그래프를 그리는 방법을 살펴봅니다.

기초적인 그래프 그리기

아래와 같이 가장 기본적인 그래프를 그릴 수 있습니다.

%matplotlib inline
import matplotlib.pyplot as plt
plt.plot([1, 3, 2, 5, 4])
plt.show();

outputs/matplotlib-first-plot.png

앞서 pandas에서 그래프를 그렸을 때와 모양이 비슷합니다. pandas는 기본적으로 matplotlib를 사용해서 그래프를 그립니다. 그래프를 그릴 때, DataFrame에 지정되어 있는 여러 부가 정보들, 즉 컬럼 이름 등을 사용하여 기본적인 그래프의 요소들을 알아서 지정합니다.

NumPy의 ndarray로 그려도 동일합니다.

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

plt.plot(np.arange(10))
plt.show();

outputs/matplotlib-first-plot-2.png

Pandas의 Series로 그려도 동일합니다.

%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt

plt.plot(pd.Series([1, 3, 2, 5, 4]))
plt.show();

outputs/matplotlib-first-plot-3.png

x축의 값을 지정하려면 아래와 같이 할 수 있습니다.

%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt

plt.plot(['2011', '2012', '2013', '2014', '2015'], [1, 3, 2, 5, 4])
plt.show();

outputs/matplotlib-first-plot-4.png

여러 계열을 동시에 그리기

여러 계열의 데이터를 동시에 그리려면 아래와 같이 합니다.

%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt

x = ['2011', '2012', '2013', '2014', '2015']
plt.plot(x, [1, 3, 2, 5, 4])
plt.plot(x, [2, 1, 3, 1, 1])
plt.show();

outputs/matplotlib-multiseries-plot-1.png

제목 표시하기

그래프의 제목과 x,y축 이름을 붙이기 위해서는 title, xlabel, ylabel 함수를 사용합니다.

%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt

plt.title('Test Plot')
plt.xlabel('Tick')
plt.ylabel('Value')
plt.plot([1, 3, 2, 5, 4])
plt.plot([2, 1, 3, 1, 1])
plt.show();

outputs/matplotlib-title-plot-1.png

범례 표시하기

범례를 표시하기 위해서는 아래와 같이 각 계열에 이름을 부여하고, plt.legend() 를 호출한 뒤 그래프를 그립니다.

%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt

plt.plot([1, 3, 2, 5, 4], label='서울')
plt.plot([2, 1, 3, 1, 1], label='부산')
plt.legend()
plt.show();

outputs/matplotlib-legend-plot-1.png

그런데 그려진 그래프에 한글이 제대로 표시되지 않는 것을 볼 수 있습니다. 이것은 적절한 한글 글꼴이 지정되지 않았기 때문입니다. 아래와 같이 폰트를 지정해줍니다. 폰트는 시스템 환경마다 다를 수 있습니다. Windows의 경우에는 ‘Malgun Gothic’, MacOS의 경우에는 ‘AppleGothic’으로 지정해보세요.

%matplotlib inline
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
matplotlib.rc('font', family='Noto Sans CJK KR')

plt.plot([1, 3, 2, 5, 4], label='서울')
plt.plot([2, 1, 3, 1, 1], label='부산')
plt.legend()
plt.show();

outputs/matplotlib-legend-plot-2.png

Grid 그리기

%matplotlib inline
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
matplotlib.rc('font', family='Noto Sans CJK KR')

x = ['2011', '2012', '2013', '2014', '2015']
plt.plot(x, [1, 3, 2, 5, 4])
plt.plot(x, [2, 1, 3, 1, 1])
plt.grid()
plt.show();

outputs/matplotlib-grid-plot-1.png

grid가 너무 촘촘하다면 yticks 함수를 사용하여 그 정도를 조절할 수 있습니다.

%matplotlib inline
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
matplotlib.rc('font', family='Noto Sans CJK KR')

x = ['2011', '2012', '2013', '2014', '2015']
plt.plot(x, [1, 3, 2, 5, 4])
plt.plot(x, [2, 1, 3, 1, 1])
plt.yticks([1, 2, 3, 4, 5])
plt.grid()
plt.show();

outputs/matplotlib-grid-plot-2.png

line plot style

선 그래프에서 선의 스타일을 변경하려면 어떻게 할까요?

%matplotlib inline
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
matplotlib.rc('font', family='Noto Sans CJK KR')

x = ['2011', '2012', '2013', '2014', '2015']
plt.plot(x, [1, 3, 2, 5, 4], 'ro')
plt.plot(x, [2, 1, 3, 1, 1], 'b--', linewidth=3)
plt.plot(x, [2, 2, 5, 2, 3], 'gs')
plt.plot(x, [7, 3, 1, 3, 7], '-o', markersize=10)
plt.grid()
plt.show();

outputs/matplotlib-plot-style-1.png

plot 함수에 데이터의 x축, y축 값을 전달하고, 곧바로 이어지는 위치 인자에 그래프의 스타일을 전달할 수 있습니다. 지정할 수 있는 스타일에는 아래와 같은 것이 있습니다:

  • 선의 스타일: ‘-‘, ‘–’, ‘-.’
  • 마커(점)의 스타일: ‘.’, ‘,’, ‘o’, ‘v’, ‘^’, ‘<’, ‘>’, ‘s’, ‘p’, ‘*’, ‘D’, …
  • 마커 및 선의 색상: ‘b’(lue), ‘g’(reen), ‘r’(ed), ‘c’(yan), ‘m’(agenta), ‘y’(ellow), ‘k’(black), ‘w’(white)

또는 아래처럼 키워드 인자로 구분해서 지정할 수도 있습니다.

%matplotlib inline
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
matplotlib.rc('font', family='Noto Sans CJK KR')

x = ['2011', '2012', '2013', '2014', '2015']
plt.plot(x, [1, 3, 2, 5, 4], color='red', marker='o', linestyle='')
plt.plot(x, [2, 1, 3, 1, 1], color='blue', linestyle='--', linewidth=3)
plt.plot(x, [2, 2, 5, 2, 3], color='g', marker='s', linestyle='')
plt.plot(x, [7, 3, 1, 3, 7], linestyle='-', marker='o', markersize=10)
plt.grid()
plt.show();

outputs/matplotlib-plot-style-2.png

figure와 axes 소개

웹상에서 matplotlib에 대한 정보를 리서치하시다보면, 위에서 소개한 것과는 다소 다른 스타일의 사용법도 발견하실 수 있습니다. 이 두 스타일의 차이점과 원리를 이해하시면 코드를 읽어 활용하는데 덜 헷깔리실겁니다.

우선 아래 개념도를 보고 matplotlib가 정의하는 그래프 구조에 대해 알아봅시다.

https://matplotlib.org/_images/anatomy.png

  • 가장 큰 요소로 figure 가 있습니다. figure 는 일종의 전체 캔버스라고 볼 수 있습니다.
  • 하나의 figure 는 여러개의 차트를 가질 수 있는데, 각 차트를 Axes 라고 부릅니다. (Axis 가 아닙니다)

본 쳅터에서 설명하던 코드를 다시 한번 살펴볼까요?

%matplotlib inline

import matplotlib.pyplot as plt

plt.plot([1, 3, 2, 5, 4])
plt.show();

outputs/matplotlib-figure-axes-1.png

위의 코드에는 실제로는 숨겨진 동작이 있습니다. 아래의 코드는 위의 코드와 동일합니다.

%matplotlib inline

import matplotlib.pyplot as plt

figure = plt.figure()           # 가장 먼저, 캔버스인 figure를 준비한다
axes = figure.add_subplot(111)  # 하나의 axes를 추가한다
axes.plot([1, 3, 2, 5, 4])      # 해당 axes에 그래프를 그린다
plt.show();                     # 표시한다

outputs/matplotlib-figure-axes-2.png

위의 코드에서는 matplotlib의 구성 요소인 figure와 axes가 명확히 드러납니다. pyplot만을 사용하는 방식에서는, plt.plot() 을 수행하면 내부적으로 기본 axes 를 생성하고, 이후 axes 에 관련된 plt 함수를 실행할 때는 기본 axes 에 대해 수행합니다.

pyplot을 사용한 간략한 스타일의 사용법은, 간단한 용도로 사용할 때는 간편하지만, 복잡하거나 정교한 제어를 할 때는 figure와 axes를 명시적으로 사용할 필요가 있습니다.

subplot 그리기

그 중 한 예가 여러 개의 그래프를 한 번에 그리는 것입니다.

subplots() 혹은 add_subplot()

%matplotlib inline

import matplotlib.pyplot as plt

figure = plt.figure()
axes_1 = figure.add_subplot(2,1,1) # subplot이 2행 1열짜리이고 첫번째 plot임
axes_1.plot([1, 3, 2, 5, 4])

axes_2 = figure.add_subplot(2,1,2) # subplot이 2행 1열짜리이고 두번째 plot임
axes_2.plot([1, 3, 2, 5, 4])
plt.show();

outputs/matplotlib-subplot-1.png

%matplotlib inline

import matplotlib.pyplot as plt

figure = plt.figure()
axes_1 = figure.add_subplot(1,2,1) # subplot이 1행 2열짜리이고 첫번째 plot임
axes_1.plot([1, 3, 2, 5, 4])

axes_2 = figure.add_subplot(1,2,2) # subplot이 2행 2열짜리이고 두번째 plot임
axes_2.plot([1, 3, 2, 5, 4])
plt.show();

outputs/matplotlib-subplot-2.png

pandas에서 matplotlib를 사용해 그래프를 정교하게 제어하기

pandasmatplotlib 를 잘 사용하면 pandas 만 알면 되지 matplotlib 를 왜 또 알아야 할까요?

아래 그래프에서, 그래프에 grid를 추가하고 싶으면 어떻게 할까요?

import pandas as pd
df = pd.DataFrame([(1, 3000), (2, 4021), (3, 4300), (4, 1200)], columns=['A', 'B'])
df.plot.line();

outputs/matplotlib-pandas-1.png

결국 기본적인 설정은 pandas 가 해주지만, 세부적인 조정을 하기 위해서는 matplotlib 를 이해하고 사용해야 합니다.

그러면 pandasmatplotlib 는 서로 어떻게 연결되어 있을까요?

사실 pandas 에서 plot 함수를 사용해서 그래프를 그릴 때, plot 은 해당 그래프에 대한 axes 객체를 반환해줍니다. 우리는 그 axes 객체를 제어하여 기본 설정된 그래프를 변경할 수 있습니다.

import pandas as pd
df = pd.DataFrame([(1, 3000), (2, 4021), (3, 4300), (4, 1200)], columns=['A', 'B'])
axes = df.plot.line()
axes.grid()

outputs/matplotlib-pandas-2.png

또는 plt 접근 방법을 통해 현재 활성화된 axes 에 접근하여 그래프를 변경할 수도 있습니다.

import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame([(1, 3000), (2, 4021), (3, 4300), (4, 1200)], columns=['A', 'B'])
df.plot.line()
plt.grid()

outputs/matplotlib-pandas-3.png

Seaborn 사용하기

matplotlib는 정교한 제어를 할 때는 적절한 도구일 수 있지만, 너무 세부적인 사항들을 많이 알아야 합니다. 특히 통계에 필요한 그래프를 그릴 때는, pandas는 너무 간단한 그래프만 그려주고, matplotlib는 너무 복잡합니다. 그 중간을 채워줄 수 있는 도구가 Seaborn입니다. Seaborn 역시 내부적으로는 matplotlib를 사용하며, 통계에 적합한 그래프를 그려줍니다.

앞서 그렸던 몇 가지 그래프를 seaborn을 사용해서 다시 그려보겠습니다.

import pandas as pd
df_dtype = pd.read_excel('outputs/실습생_컬럼추가.xlsx', sheet_name='Sheet1',
                         index_col=0,
                         dtype={'번호': 'object', '성별': 'object', '즐기는 음식': 'object', '비만도': 'object', '연령대': 'object'})
df_dtype

키와 몸무게의 상관관계를 살펴봅시다.

import seaborn as sns
sns.regplot(x='신장(cm)', y='몸무게(kg)', data=df_dtype);

outputs/matplotlib-seaborn-plot-1.png

성별에 따른 몸무게의 분포를 살펴봅시다.

sns.stripplot(x="성별", y="몸무게(kg)", data=df_dtype);

outputs/matplotlib-seaborn-plot-2.png