pandasのplotメソッドでグラフを作成しデータを可視化

Posted: | Tags: Python, pandas, Matplotlib, seaborn

pandas.Series, pandas.DataFrameのメソッドとしてplot()がある。Pythonのグラフ描画ライブラリMatplotlibのラッパーで、簡単にグラフを作成できる。

Irisデータセットを例として、様々な種類のグラフ作成および引数の設定などをサンプルコード・結果とともに説明する。

  • Irisデータセット
  • plot()メソッドの基本的な使い方
    • 表示
    • 画像ファイルとして保存
    • オブジェクトとして操作
  • 共通の設定
    • サイズを変更
    • 別々のサブプロットに描画
      • サブプロットのレイアウト
      • サブプロットのx軸, y軸の共通化
    • プロットする列の指定
    • グラフの種類
  • 折れ線グラフ(line plot)
  • 棒グラフ(bar plot)
  • 箱ひげ図(box plot)
  • ヒストグラム(histogram)
  • カーネル密度推定(Kernel Density Estimation plot)
  • 面グラフ(area plot)
  • 散布図(scatter plot)
  • 六角形ビニング図(hexbin plot)
  • ビジュアライゼーションライブラリseabornを使ったグラフ作成
    • ヒートマップ
    • ペアプロット図(散布図行列)

各種ライブラリを以下のようにインポートする。

import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt

Irisデータセット

irisデータセットは機械学習でよく使われるアヤメの品種データ。

150件のデータがSetosa, Versicolor, Virginicaの3品種に分類されており、それぞれ、Sepal Length(がく片の長さ), Sepal Width(がく片の幅), Petal Length(花びらの長さ), Petal Width(花びらの幅)の4つの特徴量を持っている。

様々なライブラリにテストデータとして入っている。

pandas.DataFrameとして読み込む。

df = pd.read_csv('data/src/iris.csv', index_col=0)

print(df.head())
#    sepal_length  sepal_width  petal_length  petal_width species
# 0           5.1          3.5           1.4          0.2  setosa
# 1           4.9          3.0           1.4          0.2  setosa
# 2           4.7          3.2           1.3          0.2  setosa
# 3           4.6          3.1           1.5          0.2  setosa
# 4           5.0          3.6           1.4          0.2  setosa

species列には3種類の品種が文字列で格納され、残り4つの列はそれぞれの特徴量が数値で格納される。

plot()メソッドの基本的な使い方

表示

pandas.Seriesまたはpandas.DataFrameからplot()メソッドを呼ぶとデフォルトでは折れ線グラフが描画される。

グラフ化されるのは数値の列のみで文字列の列は除外される。indexがx軸として使われる。

Jupyter Notebookの場合、先に%matplotlib inlineを実行しておくとグラフがインラインで表示される。

df.plot()

pandas plot default

画像ファイルとして保存

画像ファイルとして保存する場合はplt.savefig()、ファイル保存ではなくOSの画像表示プログラムで表示する場合はplt.show()を使う。

繰り返しグラフを作成する場合はplt.figure()で初期化しないと、前の結果が残ることがあるので注意。Jupyter Notebookでインライン表示する場合は特に初期化の必要はない。

また、繰り返しplt.figure()を実行すると以下のような警告が出る場合がある。

RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface
(`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. 
(To control this warning, see the rcParam `figure.max_open_warning`). max_open_warning, RuntimeWarning)

plt.savefig()のあとでplt.close('all')を実行すればOK。

plt.figure()
df.plot()
plt.savefig('data/dst/pandas_iris_line.png')
plt.close('all')

オブジェクトとして操作

plot()メソッドが返すのはMatplotlibのAxesSubplotオブジェクト。

print(type(df.plot()))
# <class 'matplotlib.axes._subplots.AxesSubplot'>

デフォルトではアクティブなサブプロットに描画されるが、plot()の引数axで任意のサブプロットを指定して描画できる。

上のpyplotインターフェイスと同様のグラフを生成する例。

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
df.plot(ax=ax)
fig.savefig('data/dst/pandas_iris_line.png')

plt.subplots()を使って複数のサブプロットを並べる例。

fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(9, 6))
df.plot(ax=axes[0, 0], legend=False)
df.plot(ax=axes[1, 2], legend=False, kind='hist')
fig.savefig('data/dst/pandas_iris_line_axes.png')

pandas plot axes

axisの細かい設定を調整したい場合などはこちらのオブジェクト指向インターフェイスを使う。

なお、引数の設定、グラフの種類によってはplot()はMatplotlibのAxesSubplotオブジェクトを要素とするNumPy配列numpy.ndarrayを返すこともあるので注意。

共通の設定

plot()では様々な種類のグラフをプロットできる。まず共通の設定を説明する。

サイズを変更

生成される画像のサイズはfigsize(単位: インチ)とdpi(インチ当たりのドット数)で決定される。

それぞれ以下のように確認および変更ができる。

figsizeはpandasのplot()メソッド、または、plt.figure(), plt.subplots()の引数として指定する。

current_figsize = mpl.rcParams['figure.figsize']
print(current_figsize)
# [6.0, 4.0]

plt.figure()
df.plot(figsize=(9, 6))
plt.savefig('data/dst/pandas_iris_line_figsize.png')
plt.close('all')

pandas plot figsize

dpisavefig()の引数として指定する。

current_dpi = mpl.rcParams['figure.dpi']
print(current_dpi)
# 72.0

plt.figure()
df.plot()
plt.savefig('data/dst/pandas_iris_line_dpi.png', dpi=current_dpi * 1.5)
plt.close('all')

pandas plot dpi

各列を別々のサブプロットにプロット: 引数subplots

引数subplots=Trueとすると各列が別々のサブプロットにプロットされる。

以降のサンプルコードではplt.figure(), plt.savefig(), plt.closeを省略する。

df.plot(subplots=True)

pandas plot subplots

この場合、AxesSubplotオブジェクトを要素とするNumPy配列numpy.ndarrayが返される。

print(type(df.plot(subplots=True)))
print(type(df.plot(subplots=True)[0]))
# <class 'numpy.ndarray'>
# <class 'matplotlib.axes._subplots.AxesSubplot'>

サブプロットのレイアウト: 引数layout

引数layoutにサブプロットの行数、列数をタプルで指定できる。

df.plot(subplots=True, layout=(2, 2))

pandas plot subplots layout

サブプロットのx軸, y軸の範囲の共通化: 引数sharex, sharey

引数sharex, shareyTrueとすると、それぞれx軸、y軸の範囲が共通化される。

df.plot(subplots=True, layout=(2, 2),
        sharex=True, sharey=True)

pandas plot subplots sharex sharey

プロットする列の指定: 引数x, y

これまでの例のように、デフォルトではpandas.DataFrameからplot()メソッドを呼ぶと、数値の列すべてがプロットされ、indexがx軸として使われる。

引数x, yに列名を指定することでx軸, y軸としてプロットする列を選択できる。例は折れ線グラフなのでよく分からない結果となるが、散布図などの場合には重要な設定。散布図については後述。

df.plot(x='sepal_length', y='sepal_width')

pandas plot xy

xのみ指定した場合は、残りの列がy軸としてプロットされる。

df.plot(x='sepal_length')

pandas plot x

yのみ指定した場合は、x軸がindex、指定した列がy軸としてプロットされる。

df.plot(y='sepal_length')

pandas plot y

引数x, yにリストで複数の列名を指定すると警告UserWarningが出る。

# df.plot(y=['sepal_length', 'sepal_width'])
# UserWarning: Pandas doesn't allow columns to be created via a new attribute name

複数の列を重ねてプロットしたい場合は、1つ目のplot()で取得できるAxesSubplotを2つ目以降のplot()の引数axに指定する。

ax = df.plot(y='sepal_length')
df.plot(y='sepal_width', ax=ax)

pandas plot multi

プロットに使う列のみを選択したpandas.DataFrameplot()メソッドを呼んでも同じ結果が得られる。こっちのほうが楽かもしれない。

df[['sepal_length', 'sepal_width']].plot()

そのほか見た目の設定

そのほか、

  • 引数title: グラフタイトル
  • 引数grid: グリッドの有無
  • 引数colormap: 色
  • 引数legend: 凡例の有無
  • 引数alpha: 透過率(0〜1)

などが設定できる。

df.plot(title='Iris Data Set',
        grid=True,
        colormap='Accent',
        legend=False,
        alpha=0.5)

pandas plot etc

colormapで指定できる色(カラーマップ)の種類は以下のMatplotlibの公式サイトを参照。

グラフの種類: 引数kind

引数kindでグラフの種類を指定できる。

  • 'line': 折れ線グラフ(line plot)
  • 'bar': 垂直棒グラフ(vertical bar plot)
  • 'barh': 水平棒グラフ(horizontal bar plot)
  • 'box': 箱ひげ図(boxplot)
  • 'hist' : ヒストグラム(histogram)
  • 'kde', 'density': カーネル密度推定(Kernel Density Estimation plot)
  • 'area': 面グラフ(area plot)
  • 'scatter': 散布図(scatter plot)
  • 'hexbin': hexbin plot
  • 'pie': 円グラフ(pie plot)

バージョン0.17.0から、上記のグラフの種類をplot()メソッドのアクセサとして記述できるようになった。

例えばdf.plot(kind='line')df.plot.line()は同じ。

df.plot(kind='line')
df.plot.line()

pandas plot line

plot.line()でもここまで説明してきたplot()の引数がそのまま使える。

df.plot.line(subplots=True, layout=(2, 2))

pandas plot subolots layout

それぞれのグラフの種類に対応するMatplotlibのメソッドの引数もキーワード引数として設定できる。

折れ線グラフ(line plot)

折れ線グラフはplot.line()

線種や色、マーカーは引数styleに文字列'[color][marker][line]'で指定する。

  • color: r(赤), g(緑), b(青), k(黒)など
  • marker: o(丸), .(点), s(四角), +(プラス)など
  • line: -(破線), --(破線), :(点線)など

例えば赤い破線に四角のマーカーは'rs--'color, marker, lineをすべて含む必要はなく、省略も可能。

それぞれの種類一覧は以下のMatplotlib公式サイト参照。中段のNoteに書いてある。

各プロットに対して個別に指定したい場合は引数styleに文字列のリストを指定する。

df.plot.line(style=['r--', 'b.-', 'g+', 'k:'])

pandas plot line style

棒グラフ(bar plot)

垂直棒グラフはplot.bar(), 水平棒グラフはplot.barh()

行数が多いと見にくいので最初の5行分のデータのみ使用している。

df[:5].plot.bar()

pandas plot bar

df[:5].plot.barh()

pandas plot barh

引数stacked=Trueとすると積み上げ棒グラフになる。

df[:5].plot.bar(stacked=True)

pandas plot bar stacked

棒グラフ独自の引数はMatplotlibの公式サイト参照。

箱ひげ図(box plot)

箱ひげ図はplot.box()

最小値、第1四分位点、中央値、第3四分位点、最大値が表される。丸は外れ値。

df.plot.box()

pandas plot box

箱ひげ図独自の引数はMatplotlibの公式サイト参照。

ヒストグラム(histogram)

ヒストグラムはplot.hist()

plt.savefig('data/dst/pandas_iris_hist.png')

pandas plot histogram

透過率は引数alpha

df.plot.hist(alpha=0.5)

pandas plot histogram alpha

引数stacked=Trueで積み上げヒストグラム。

df.plot.hist(stacked=True)

pandas plot histogram stack

ヒストグラム独自の引数はMatplotlibの公式サイト参照。

引数binsで分割数を指定したり、histtypeでタイプを指定したり、orientationで横向きにしたりできる。

df.plot.hist(bins=20, histtype='step', orientation='horizontal')

pandas plot histogram bins type orientation

カーネル密度推定(Kernel Density Estimation plot)

カーネル密度推定の分布図はplot.kde()

線の種類、色は折れ線グラフと同様、引数styleで指定できる。上の折れ線グラフの項を参照。

df.plot.kde(style=['r-', 'g--', 'b-.', 'c:'])

pandas plot kde

面グラフ(area plot)

面グラフはplot.area()

デフォルトで積み上げ面グラフとなる。積み上げを無効にしたい場合は引数stacked=False

df.plot.area()

pandas plot area

散布図(scatter plot)

散布図はplot.scatter()

x軸、y軸としてプロットする列の列名をそれぞれ引数x, yに指定する。

df.plot.scatter(x='sepal_length', y='petal_length', alpha=0.5)

pandas plot scatter

上の共通の設定の項で説明したように、複数のプロットを重ねる場合は1つ目のplot()で取得できるAxesSubplotを2つ目以降のplot()の引数axに指定する。

マーカーの種類は引数marker、色は引数c、サイズは引数sで指定する。csはリストで指定することも可能。

そのほか散布図独自の引数はMatplotlibの公式サイト参照。

ax = df.plot.scatter(x='sepal_length', y='petal_length', alpha=0.5)
df.plot.scatter(x='sepal_length', y='petal_width',
                marker='s', c='r', s=50, alpha=0.5, ax=ax)

pandas plot scatter multi

なお、折れ線グラフの引数styleでマーカーを指定して線種を省略すると散布図と同様のグラフが描画できる。こっちのほうが楽かもしれない。お好みで。

df.plot.line(x='sepal_length',
             style=['ro', 'g+', 'bs'], alpha=0.5)

pandas plot scatter using line plot

六角形ビニング図(hexbin plot)

日本語の正しい名称を知らないが、散布図での六角形のエリアに入る点の数を色の濃さで表したグラフ。同じ位置に多数の点が重なってプロットされるようなデータの分布が見やすい。

散布図と同様にx軸、y軸としてプロットする列の列名をそれぞれ引数x, yに指定する。

hexbin独自の引数はMatplotlibの公式サイト参照。

引数gridsizeはx軸方向の六角形の数。小さくなると六角形が大きく、粗いグラフになる。

df.plot.hexbin(x='sepal_length', y='petal_length',
               gridsize=15, sharex=False)

pandas plot hexbin

デフォルトだとx軸のラベルが表示されないpandasのバグがある。バージョン0.22.0時点でまだFixされていないが、sharex=Falseとすればとりあえず表示されるようになる。

円グラフ(pie plot)

円グラフはplot.pie()

Irisのデータだとよく分からないので別のデータを例とする。

df_pie = pd.DataFrame([[1, 50], [2, 20], [3, 30]],
                      index=['a', 'b', 'c'], columns=['ONE', 'TWO'])

print(df_pie)
#    ONE  TWO
# a    1   50
# b    2   20
# c    3   30

pandas.DataFrameに対しては引数subplots=Trueとして列毎に個別にプロットしないとエラーになる。

df_pie.plot.pie(subplots=True)

pandas plot pie

AxesSubplotオブジェクトを要素とするNumPy配列numpy.ndarrayが返される。

print(type(df_pie.plot.pie(subplots=True)))
print(type(df_pie.plot.pie(subplots=True)[0]))
# <class 'numpy.ndarray'>
# <class 'matplotlib.axes._subplots.AxesSubplot'>

特定の列の円グラフを生成したい場合は、列を指定してplot.pie()を呼ぶ。

df_pie['ONE'].plot.pie()

pandas plot pie single

ビジュアライゼーションライブラリseabornを使ったグラフ作成

ビジュアライゼーションライブラリseabornを使うとそのほかの種類のグラフを作成できる。

ヒートマップ

二次元データからヒートマップを作成できる。

pandas.DataFrameを使うと列名・行名がそのままx軸・y軸のラベルになる。

下の例はIrisではなく別のデータの各列間の相関係数を可視化したもの。

seaborn heatmap example kaggle house prices

詳細は以下の記事を参照。

ペアプロット図(散布図行列)

ペアプロット図(散布図行列)も作成できる。

列同士の関係をざっくり確認するのに便利。

seaborn pairplot kind reg

詳細は以下の記事を参照。

関連カテゴリー

関連記事