グラフによる可視化#

注記

以下の例では、Jupyterを使用していることを前提としています。

このセクションでは、グラフによる可視化を示します。表形式データの可視化については、表形式の可視化のセクションを参照してください。

matplotlib APIへの参照には標準的な表記法を使用します。

In [1]: import matplotlib.pyplot as plt

In [2]: plt.close("all")

pandasでは、見栄えの良いプロットを簡単に作成するための基本的な機能を提供しています。ここで説明されている基本機能を超えた可視化ライブラリについては、エコシステムページを参照してください。

注記

np.randomへのすべての呼び出しは、123456でシードされています。

基本的なプロット:plot#

基本事項を説明します。高度な戦略については、クックブックを参照してください。

SeriesとDataFrameのplotメソッドは、plt.plot()のシンプルなラッパーです。

In [3]: np.random.seed(123456)

In [4]: ts = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000))

In [5]: ts = ts.cumsum()

In [6]: ts.plot();
../_images/series_plot_basic.png

インデックスが日付で構成されている場合、上記のようにx軸を適切にフォーマットしようとgcf().autofmt_xdate()を呼び出します。

DataFrameでは、plot()は、すべての列をラベル付きでプロットするための便利な方法です。

In [7]: df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=list("ABCD"))

In [8]: df = df.cumsum()

In [9]: plt.figure();

In [10]: df.plot();
../_images/frame_plot_basic.png

plot()xyキーワードを使用して、ある列を別の列に対してプロットできます。

In [11]: df3 = pd.DataFrame(np.random.randn(1000, 2), columns=["B", "C"]).cumsum()

In [12]: df3["A"] = pd.Series(list(range(len(df))))

In [13]: df3.plot(x="A", y="B");
../_images/df_plot_xy.png

注記

より詳細なフォーマットとスタイルのオプションについては、下記のフォーマットを参照してください。

その他のプロット#

プロットメソッドでは、デフォルトの折れ線グラフ以外のいくつかのプロットスタイルを使用できます。これらのメソッドは、plot()kindキーワード引数として指定でき、以下が含まれます。

例えば、棒グラフは次のように作成できます。

In [14]: plt.figure();

In [15]: df.iloc[5].plot(kind="bar");
../_images/bar_plot_ex.png

kindキーワード引数を指定する代わりに、DataFrame.plot.<kind>メソッドを使用することもできます。これにより、プロットメソッドとその使用方法を簡単に確認できます。

In [16]: df = pd.DataFrame()

In [17]: df.plot.<TAB>  # noqa: E225, E999
df.plot.area     df.plot.barh     df.plot.density  df.plot.hist     df.plot.line     df.plot.scatter
df.plot.bar      df.plot.box      df.plot.hexbin   df.plot.kde      df.plot.pie

これらのkindに加えて、DataFrame.hist()DataFrame.boxplot()メソッドがあり、これらは別々のインターフェースを使用します。

最後に、プロット関数pandas.plottingにいくつかあり、SeriesまたはDataFrameを引数として受け取ります。これらには以下が含まれます。

プロットには、エラーバーまたはを付けることもできます。

棒グラフ#

ラベル付きの非時系列データの場合、棒グラフを作成したい場合があります。

In [18]: plt.figure();

In [19]: df.iloc[5].plot.bar();

In [20]: plt.axhline(0, color="k");
../_images/bar_plot_ex.png

DataFrameのplot.bar()メソッドを呼び出すと、複数の棒グラフが作成されます。

In [21]: df2 = pd.DataFrame(np.random.rand(10, 4), columns=["a", "b", "c", "d"])

In [22]: df2.plot.bar();
../_images/bar_plot_multi_ex.png

積み上げ棒グラフを作成するには、stacked=Trueを渡します。

In [23]: df2.plot.bar(stacked=True);
../_images/bar_plot_stacked_ex.png

横棒グラフを取得するには、barhメソッドを使用します。

In [24]: df2.plot.barh(stacked=True);
../_images/barh_plot_stacked_ex.png

ヒストグラム#

ヒストグラムは、DataFrame.plot.hist()Series.plot.hist()メソッドを使用して描画できます。

In [25]: df4 = pd.DataFrame(
   ....:     {
   ....:         "a": np.random.randn(1000) + 1,
   ....:         "b": np.random.randn(1000),
   ....:         "c": np.random.randn(1000) - 1,
   ....:     },
   ....:     columns=["a", "b", "c"],
   ....: )
   ....: 

In [26]: plt.figure();

In [27]: df4.plot.hist(alpha=0.5);
../_images/hist_new.png

ヒストグラムはstacked=Trueを使用して積み重ねることができます。ビンサイズはbinsキーワードを使用して変更できます。

In [28]: plt.figure();

In [29]: df4.plot.hist(stacked=True, bins=20);
../_images/hist_new_stacked.png

matplotlib histでサポートされている他のキーワードを渡すことができます。例えば、水平ヒストグラムと累積ヒストグラムは、orientation='horizontal'cumulative=Trueで描画できます。

In [30]: plt.figure();

In [31]: df4["a"].plot.hist(orientation="horizontal", cumulative=True);
../_images/hist_new_kwargs.png

histメソッドとmatplotlibヒストグラムのドキュメントの詳細を参照してください。

ヒストグラムのプロットを行う既存のインターフェースDataFrame.histはまだ使用できます。

In [32]: plt.figure();

In [33]: df["A"].diff().hist();
../_images/hist_plot_ex.png

DataFrame.hist()は、複数のサブプロット上に列のヒストグラムをプロットします。

In [34]: plt.figure();

In [35]: df.diff().hist(color="k", alpha=0.5, bins=50);
../_images/frame_hist_ex.png

byキーワードを指定して、グループ化されたヒストグラムをプロットできます。

In [36]: data = pd.Series(np.random.randn(1000))

In [37]: data.hist(by=np.random.randint(0, 4, 1000), figsize=(6, 4));
../_images/grouped_hist.png

さらに、byキーワードはDataFrame.plot.hist()でも指定できます。

バージョン1.4.0で変更されました。

In [38]: data = pd.DataFrame(
   ....:     {
   ....:         "a": np.random.choice(["x", "y", "z"], 1000),
   ....:         "b": np.random.choice(["e", "f", "g"], 1000),
   ....:         "c": np.random.randn(1000),
   ....:         "d": np.random.randn(1000) - 1,
   ....:     },
   ....: )
   ....: 

In [39]: data.plot.hist(by=["a", "b"], figsize=(10, 5));
../_images/grouped_hist_by.png

箱ひげ図#

箱ひげ図は、Series.plot.box()DataFrame.plot.box()、またはDataFrame.boxplot()を呼び出して、各列内の値の分布を視覚化できます。

例えば、[0,1)の一様乱数に関する10個の観測値の5回の試行を表す箱ひげ図を以下に示します。

In [40]: df = pd.DataFrame(np.random.rand(10, 5), columns=["A", "B", "C", "D", "E"])

In [41]: df.plot.box();
../_images/box_plot_new.png

Boxplot は、color キーワードを渡すことで色付けできます。boxeswhiskersmedianscaps をキーとする dict を渡すことができます。 dict に一部のキーが欠けている場合、対応するアーティストにはデフォルトの色が使用されます。また、boxplot には、外れ値のスタイルを指定するための sym キーワードがあります。

color キーワードを介して他の型の引数を渡すと、すべての boxeswhiskersmedianscaps の色付けに matplotlib に直接渡されます。

色は描画されるすべてのボックスに適用されます。より複雑な色付けが必要な場合は、return_type を渡すことで、描画された各アーティストを取得できます。

In [42]: color = {
   ....:     "boxes": "DarkGreen",
   ....:     "whiskers": "DarkOrange",
   ....:     "medians": "DarkBlue",
   ....:     "caps": "Gray",
   ....: }
   ....: 

In [43]: df.plot.box(color=color, sym="r+");
../_images/box_new_colorize.png

また、matplotlib boxplot でサポートされている他のキーワードを渡すこともできます。例えば、vert=Falsepositions キーワードを使用して、水平方向およびカスタム位置の boxplot を描画できます。

In [44]: df.plot.box(vert=False, positions=[1, 4, 5, 6, 8]);
../_images/box_new_kwargs.png

詳細は、boxplot メソッドと matplotlib boxplot のドキュメント を参照してください。

boxplot をプロットするための既存のインターフェース DataFrame.boxplot は引き続き使用できます。

In [45]: df = pd.DataFrame(np.random.rand(10, 5))

In [46]: plt.figure();

In [47]: bp = df.boxplot()
../_images/box_plot_ex.png

by キーワード引数を使用してグループを作成することで、層別 boxplot を作成できます。例えば、

In [48]: df = pd.DataFrame(np.random.rand(10, 2), columns=["Col1", "Col2"])

In [49]: df["X"] = pd.Series(["A", "A", "A", "A", "A", "B", "B", "B", "B", "B"])

In [50]: plt.figure();

In [51]: bp = df.boxplot(by="X")
../_images/box_plot_ex2.png

複数の列でグループ化する場合と同様に、プロットする列のサブセットを渡すこともできます。

In [52]: df = pd.DataFrame(np.random.rand(10, 3), columns=["Col1", "Col2", "Col3"])

In [53]: df["X"] = pd.Series(["A", "A", "A", "A", "A", "B", "B", "B", "B", "B"])

In [54]: df["Y"] = pd.Series(["A", "B", "A", "B", "A", "B", "A", "B", "A", "B"])

In [55]: plt.figure();

In [56]: bp = df.boxplot(column=["Col1", "Col2"], by=["X", "Y"])
../_images/box_plot_ex3.png

例えば、DataFrame.plot.box() を使用してグループを作成することもできます。

バージョン1.4.0で変更されました。

In [57]: df = pd.DataFrame(np.random.rand(10, 3), columns=["Col1", "Col2", "Col3"])

In [58]: df["X"] = pd.Series(["A", "A", "A", "A", "A", "B", "B", "B", "B", "B"])

In [59]: plt.figure();

In [60]: bp = df.plot.box(column=["Col1", "Col2"], by="X")
../_images/box_plot_ex4.png

boxplot では、return_type キーワードで戻り値の型を制御できます。有効な選択肢は {"axes", "dict", "both", None} です。by キーワードを使用して DataFrame.boxplot で作成されたファセットは、出力型にも影響します。

return_type

ファセット

出力型

None

いいえ

axes

None

はい

axes の 2 次元 ndarray

'axes'

いいえ

axes

'axes'

はい

axes の Series

'dict'

いいえ

アーティストの辞書

'dict'

はい

アーティストの辞書の Series

'both'

いいえ

namedtuple

'both'

はい

namedtuple の Series

Groupby.boxplot は常に return_typeSeries を返します。

In [61]: np.random.seed(1234)

In [62]: df_box = pd.DataFrame(np.random.randn(50, 2))

In [63]: df_box["g"] = np.random.choice(["A", "B"], size=50)

In [64]: df_box.loc[df_box["g"] == "B", 1] += 3

In [65]: bp = df_box.boxplot(by="g")
../_images/boxplot_groupby.png

上記のサブプロットは、まず数値列、次に g 列の値で分割されます。サブプロットの下では、まず g の値で、次に数値列で分割されます。

In [66]: bp = df_box.groupby("g").boxplot()
../_images/groupby_boxplot_vis.png

面積図#

Series.plot.area()DataFrame.plot.area() を使用して面積図を作成できます。面積図はデフォルトで積み重ねられます。積み重ねられた面積図を作成するには、各列がすべて正の値かすべて負の値のいずれかである必要があります。

入力データに NaN が含まれる場合、自動的に 0 で埋められます。異なる値でドロップまたは埋め込む場合は、plot を呼び出す前に dataframe.dropna() または dataframe.fillna() を使用してください。

In [67]: df = pd.DataFrame(np.random.rand(10, 4), columns=["a", "b", "c", "d"])

In [68]: df.plot.area();
../_images/area_plot_stacked.png

積み重ねられていないプロットを作成するには、stacked=False を渡します。アルファ値は、特に指定がない限り 0.5 に設定されます。

In [69]: df.plot.area(stacked=False);
../_images/area_plot_unstacked.png

散布図#

DataFrame.plot.scatter() メソッドを使用して散布図を描画できます。散布図には、x 軸と y 軸に数値列が必要です。これらは、xy キーワードで指定できます。

In [70]: df = pd.DataFrame(np.random.rand(50, 4), columns=["a", "b", "c", "d"])

In [71]: df["species"] = pd.Categorical(
   ....:     ["setosa"] * 20 + ["versicolor"] * 20 + ["virginica"] * 10
   ....: )
   ....: 

In [72]: df.plot.scatter(x="a", y="b");
../_images/scatter_plot.png

単一の axes に複数の列グループをプロットするには、ターゲット ax を指定して plot メソッドを繰り返します。各グループを区別するために、colorlabel キーワードを指定することをお勧めします。

In [73]: ax = df.plot.scatter(x="a", y="b", color="DarkBlue", label="Group 1")

In [74]: df.plot.scatter(x="c", y="d", color="DarkGreen", label="Group 2", ax=ax);
../_images/scatter_plot_repeated.png

c キーワードは、各点の色を指定する列の名前として渡すことができます。

In [75]: df.plot.scatter(x="a", y="b", c="c", s=50);
../_images/scatter_plot_colored.png

c にカテゴリ列を渡すと、離散的なカラーバーが生成されます。

バージョン 1.3.0 で追加。

In [76]: df.plot.scatter(x="a", y="b", c="species", cmap="viridis", s=50);
../_images/scatter_plot_categorical.png

matplotlib scatter でサポートされている他のキーワードを渡すことができます。以下の例は、DataFrame の列をバブルサイズとして使用するバブルチャートを示しています。

In [77]: df.plot.scatter(x="a", y="b", s=df["c"] * 200);
../_images/scatter_plot_bubble.png

詳細は、scatter メソッドと matplotlib scatter のドキュメント を参照してください。

六角ビン図#

DataFrame.plot.hexbin() を使用して六角ビン図を作成できます。六角ビン図は、データが密集しすぎて個々の点をプロットできない場合に、散布図の便利な代替手段となります。

In [78]: df = pd.DataFrame(np.random.randn(1000, 2), columns=["a", "b"])

In [79]: df["b"] = df["b"] + np.arange(1000)

In [80]: df.plot.hexbin(x="a", y="b", gridsize=25);
../_images/hexbin_plot.png

便利なキーワード引数は gridsize です。これは x 方向の六角形の数を制御し、デフォルトは 100 です。gridsize が大きいほど、より多くの小さなビンになります。

デフォルトでは、各 (x, y) 点の周りのカウントのヒストグラムが計算されます。Creduce_C_function 引数に値を渡すことで、代替集計を指定できます。C は各 (x, y) 点の値を指定し、reduce_C_function は、ビンのすべての値を単一の数字に減らす 1 つの引数の関数です(例:meanmaxsumstd)。この例では、位置は列 ab で与えられ、値は列 z で与えられます。ビンは NumPy の max 関数で集計されます。

In [81]: df = pd.DataFrame(np.random.randn(1000, 2), columns=["a", "b"])

In [82]: df["b"] = df["b"] + np.arange(1000)

In [83]: df["z"] = np.random.uniform(0, 3, 1000)

In [84]: df.plot.hexbin(x="a", y="b", C="z", reduce_C_function=np.max, gridsize=25);
../_images/hexbin_plot_agg.png

詳細は、hexbin メソッドと matplotlib hexbin のドキュメント を参照してください。

円グラフ#

DataFrame.plot.pie() または Series.plot.pie() を使用して円グラフを作成できます。データに NaN が含まれる場合、自動的に 0 で埋められます。データに負の値が含まれている場合、ValueError が発生します。

In [85]: series = pd.Series(3 * np.random.rand(4), index=["a", "b", "c", "d"], name="series")

In [86]: series.plot.pie(figsize=(6, 6));
../_images/series_pie_plot.png

円グラフには、正方形の図形、つまり縦横比が 1 の図形を使用するのが最適です。幅と高さが等しい図形を作成するか、返された axes オブジェクトに ax.set_aspect('equal') を呼び出すことで、プロット後に縦横比を強制的に等しくすることができます。

DataFrame を使用した円グラフでは、y 引数または subplots=True を指定する必要があります。y が指定されている場合、選択された列の円グラフが描画されます。subplots=True が指定されている場合、各列の円グラフがサブプロットとして描画されます。デフォルトでは各円グラフに凡例が表示されます。非表示にするには legend=False を指定します。

In [87]: df = pd.DataFrame(
   ....:     3 * np.random.rand(4, 2), index=["a", "b", "c", "d"], columns=["x", "y"]
   ....: )
   ....: 

In [88]: df.plot.pie(subplots=True, figsize=(8, 4));
../_images/df_pie_plot.png

labelscolors キーワードを使用して、各ウェッジのラベルと色を指定できます。

警告

ほとんどのpandasプロットは、label引数とcolor引数を使用します(「s」がないことに注意してください)。matplotlib.pyplot.pie()と整合性を保つには、labelscolorsを使用する必要があります。

ウェッジラベルを非表示にするには、labels=Noneを指定します。fontsizeが指定されている場合、その値はウェッジラベルに適用されます。matplotlib.pyplot.pie()でサポートされている他のキーワードも使用できます。

In [89]: series.plot.pie(
   ....:     labels=["AA", "BB", "CC", "DD"],
   ....:     colors=["r", "g", "b", "c"],
   ....:     autopct="%.2f",
   ....:     fontsize=20,
   ....:     figsize=(6, 6),
   ....: );
   ....: 
../_images/series_pie_plot_options.png

合計が1.0未満の値を渡すと、合計が1になるように再スケーリングされます。

In [90]: series = pd.Series([0.1] * 4, index=["a", "b", "c", "d"], name="series2")

In [91]: series.plot.pie(figsize=(6, 6));
../_images/series_pie_plot_semi.png

詳細は、matplotlib pie ドキュメントを参照してください。

欠損値のあるデータのプロット#

pandasは、欠損値を含むDataFramesまたはSeriesのプロットについて、実用的なアプローチを取ろうとしています。欠損値は、プロットの種類に応じて削除、省略、または補完されます。

プロットの種類

NaNの処理

折れ線グラフ

NaNで空白を残す

積み上げ折れ線グラフ

0で埋める

棒グラフ

0で埋める

散布図

NaNを削除する

ヒストグラム

NaNを削除する(列方向)

箱ひげ図

NaNを削除する(列方向)

面グラフ

0で埋める

カーネル密度推定(KDE)

NaNを削除する(列方向)

ヘキサビン図

NaNを削除する

円グラフ

0で埋める

これらのデフォルトが望ましくない場合、または欠損値の処理方法を明示的に指定したい場合は、プロットする前にfillna()またはdropna()を使用することを検討してください。

プロットツール#

これらの関数はpandas.plottingからインポートでき、SeriesまたはDataFrameを引数として受け取ります。

散布行列プロット#

pandas.plottingscatter_matrixメソッドを使用して、散布行列プロットを作成できます。

In [92]: from pandas.plotting import scatter_matrix

In [93]: df = pd.DataFrame(np.random.randn(1000, 4), columns=["a", "b", "c", "d"])

In [94]: scatter_matrix(df, alpha=0.2, figsize=(6, 6), diagonal="kde");
../_images/scatter_matrix_kde.png

密度プロット#

Series.plot.kde()メソッドとDataFrame.plot.kde()メソッドを使用して、密度プロットを作成できます。

In [95]: ser = pd.Series(np.random.randn(1000))

In [96]: ser.plot.kde();
../_images/kde_plot.png

アンドリュース曲線#

アンドリュース曲線を使用すると、サンプルの属性をフーリエ級数の係数として使用して作成された多数の曲線として、多変量データをプロットできます。詳細については、Wikipediaのエントリを参照してください。これらの曲線をクラスごとに異なる色で着色することで、データのクラスタリングを視覚化できます。同じクラスのサンプルに属する曲線は通常、互いに近づき、より大きな構造を形成します。

注記:「Iris」データセットはこちらで入手できます。

In [97]: from pandas.plotting import andrews_curves

In [98]: data = pd.read_csv("data/iris.data")

In [99]: plt.figure();

In [100]: andrews_curves(data, "Name");
../_images/andrews_curves.png

平行座標#

平行座標は、多変量データをプロットするためのプロット手法です。概要については、Wikipediaのエントリを参照してください。平行座標を使用すると、データのクラスタを視覚的に確認し、他の統計量を視覚的に推定できます。平行座標を使用すると、点は接続された線分として表されます。各垂直線は1つの属性を表します。1組の接続された線分は1つのデータポイントを表します。クラスタリングする傾向のある点は、互いに近づいて表示されます。

In [101]: from pandas.plotting import parallel_coordinates

In [102]: data = pd.read_csv("data/iris.data")

In [103]: plt.figure();

In [104]: parallel_coordinates(data, "Name");
../_images/parallel_coordinates.png

ラグプロット#

ラグプロットは、データセットまたは時系列がランダムかどうかを確認するために使用されます。ランダムデータは、ラグプロットに構造を示してはなりません。非ランダムな構造は、基礎となるデータがランダムではないことを意味します。lag引数を渡すことができ、lag=1の場合、プロットは基本的にdata[:-1]data[1:]になります。

In [105]: from pandas.plotting import lag_plot

In [106]: plt.figure();

In [107]: spacing = np.linspace(-99 * np.pi, 99 * np.pi, num=1000)

In [108]: data = pd.Series(0.1 * np.random.rand(1000) + 0.9 * np.sin(spacing))

In [109]: lag_plot(data);
../_images/lag_plot.png

自己相関プロット#

自己相関プロットは、時系列のランダム性をチェックするために頻繁に使用されます。これは、さまざまな時間ラグでのデータ値の自己相関を計算することによって行われます。時系列がランダムな場合、そのような自己相関は、あらゆる時間ラグ分離に対してゼロに近いはずです。時系列が非ランダムな場合、1つ以上の自己相関が有意にゼロ以外になります。プロットに表示される水平線は、95%と99%の信頼区間に対応します。破線は99%の信頼区間です。自己相関プロットの詳細については、Wikipediaのエントリを参照してください。

In [110]: from pandas.plotting import autocorrelation_plot

In [111]: plt.figure();

In [112]: spacing = np.linspace(-9 * np.pi, 9 * np.pi, num=1000)

In [113]: data = pd.Series(0.7 * np.random.rand(1000) + 0.3 * np.sin(spacing))

In [114]: autocorrelation_plot(data);
../_images/autocorrelation_plot.png

ブートストラッププロット#

ブートストラッププロットは、平均、中央値、中間値などの統計量の不確実性を視覚的に評価するために使用されます。指定されたサイズのランダムなサブセットがデータセットから選択され、このサブセットについて対象の統計量が計算され、プロセスが指定された回数繰り返されます。結果のプロットとヒストグラムがブートストラッププロットを構成します。

In [115]: from pandas.plotting import bootstrap_plot

In [116]: data = pd.Series(np.random.rand(1000))

In [117]: bootstrap_plot(data, size=50, samples=500, color="grey");
../_images/bootstrap_plot.png

RadViz#

RadVizは、多変量データを視覚化する方法です。単純なバネ張力最小化アルゴリズムに基づいています。基本的には、平面に複数の点を設定します。ここでは、単位円上に等間隔に配置されています。各点は単一の属性を表します。次に、データセット内の各サンプルが、その属性の数値に比例する剛性を持つバネによってこれらの点のそれぞれに接続されていると仮定します(単位区間で正規化されます)。サンプルが落ち着く平面上の点(サンプルに作用する力が平衡状態にある点)は、サンプルを表す点が描画される場所です。サンプルが属するクラスに応じて、異なる色で着色されます。詳細については、RパッケージRadvizを参照してください。

注記:「Iris」データセットはこちらで入手できます。

In [118]: from pandas.plotting import radviz

In [119]: data = pd.read_csv("data/iris.data")

In [120]: plt.figure();

In [121]: radviz(data, "Name");
../_images/radviz.png

プロットのフォーマット#

プロットスタイルの設定#

バージョン1.5以降、matplotlibは事前に構成されたさまざまなプロットスタイルを提供しています。スタイルを設定することで、プロットに簡単に必要な外観を与えることができます。スタイルの設定は、プロットを作成する前にmatplotlib.style.use(my_plot_style)を呼び出すだけで簡単に行えます。たとえば、ggplotスタイルのプロットにはmatplotlib.style.use('ggplot')と記述できます。

使用可能なさまざまなスタイル名はmatplotlib.style.availableで確認でき、簡単に試すことができます。

一般的なプロットスタイル引数#

ほとんどのプロットメソッドには、返されるプロットのレイアウトとフォーマットを制御するキーワード引数のセットがあります。

In [122]: plt.figure();

In [123]: ts.plot(style="k--", label="Series");
../_images/series_plot_basic2.png

各プロットの種類(例:linebarscatter)について、追加の引数キーワードは対応するmatplotlib関数(ax.plot()ax.bar()ax.scatter())に渡されます。これらは、pandasが提供するもの以外にも、追加のスタイルを制御するために使用できます。

凡例の制御#

デフォルトで表示される凡例を非表示にするには、legend引数をFalseに設定します。

In [124]: df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=list("ABCD"))

In [125]: df = df.cumsum()

In [126]: df.plot(legend=False);
../_images/frame_plot_basic_noleg.png

ラベルの制御#

プロットにx軸とy軸のカスタムラベルを付けるには、xlabel引数とylabel引数を設定します。デフォルトでは、pandasはインデックス名をxlabelとして取得し、ylabelは空のままにします。


In [127]: df.plot();

In [128]: df.plot(xlabel="new x", ylabel="new y");
../_images/plot_xlabel_ylabel.png

スケール#

対数スケールのY軸を取得するには、logyを渡します。

In [129]: ts = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000))

In [130]: ts = np.exp(ts.cumsum())

In [131]: ts.plot(logy=True);
../_images/series_plot_logy.png

logxおよびloglogキーワード引数も参照してください。

2次y軸へのプロット#

2次y軸にデータをプロットするには、secondary_yキーワードを使用します。

In [132]: df["A"].plot();

In [133]: df["B"].plot(secondary_y=True, style="g");
../_images/series_plot_secondary_y.png

DataFrameの一部の列をプロットするには、列名をsecondary_yキーワードに指定します。

In [134]: plt.figure();

In [135]: ax = df.plot(secondary_y=["A", "B"])

In [136]: ax.set_ylabel("CD scale");

In [137]: ax.right_ax.set_ylabel("AB scale");
../_images/frame_plot_secondary_y.png

2次y軸にプロットされた列には、凡例に「(right)」と自動的にマークされます。自動マークをオフにするには、mark_right=Falseキーワードを使用します。

In [138]: plt.figure();

In [139]: df.plot(secondary_y=["A", "B"], mark_right=False);
../_images/frame_plot_secondary_y_no_right.png

時系列プロットのカスタムフォーマッタ#

pandasは、時系列プロットのカスタムフォーマッタを提供します。これらは、日付と時刻の軸ラベルのフォーマットを変更します。デフォルトでは、カスタムフォーマッタは、DataFrame.plot()またはSeries.plot()を使用してpandasによって作成されたプロットにのみ適用されます。matplotlibによって作成されたプロットを含むすべてプロットに適用するには、オプションpd.options.plotting.matplotlib.register_converters = Trueを設定するか、pandas.plotting.register_matplotlib_converters()を使用します。

ティック解像度調整の抑制#

pandasには、定期的な頻度の時系列データに対する自動ティック解像度調整が含まれています。pandasが頻度情報を推測できない限られたケース(たとえば、外部で作成されたtwinxなど)では、整合性の目的でこの動作を抑制することを選択できます。

デフォルトの動作を次に示します。x軸のティックのラベル付け方法に注意してください。

In [140]: plt.figure();

In [141]: df["A"].plot();
../_images/ser_plot_suppress.png

x_compat パラメータを使用すると、この動作を抑制できます。

In [142]: plt.figure();

In [143]: df["A"].plot(x_compat=True);
../_images/ser_plot_suppress_parm.png

抑制するプロットが複数ある場合は、pandas.plotting.plot_paramsuse メソッドを with 文で使用できます。

In [144]: plt.figure();

In [145]: with pd.plotting.plot_params.use("x_compat", True):
   .....:     df["A"].plot(color="r")
   .....:     df["B"].plot(color="g")
   .....:     df["C"].plot(color="b")
   .....: 
../_images/ser_plot_suppress_context.png

自動日付目盛調整#

TimedeltaIndex は現在、ネイティブの matplotlib 目盛ロケータメソッドを使用しています。 tickラベルが重なる図の場合は、matplotlib から自動日付目盛調整を呼び出すと便利です。

autofmt_xdate メソッドとmatplotlib のドキュメントを参照してください。

サブプロット#

DataFrame 内の各 Series は、subplots キーワードを使用して異なる軸にプロットできます。

In [146]: df.plot(subplots=True, figsize=(6, 6));
../_images/frame_plot_subplots.png

レイアウトと複数の軸のターゲット指定の使用#

サブプロットのレイアウトは、layout キーワードで指定できます。 (rows, columns) を受け付けます。layout キーワードは、histboxplot でも使用できます。入力が無効な場合は、ValueError が発生します。

layout で指定された rows × columns で格納できる軸の数は、必要なサブプロットの数より大きくなければなりません。レイアウトに必要な数より多くの軸を格納できる場合、空の軸は描画されません。NumPy 配列の reshape メソッドと同様に、一方の次元を -1 にして、もう一方の次元から必要な行数または列数を自動的に計算できます。

In [147]: df.plot(subplots=True, layout=(2, 3), figsize=(6, 6), sharex=False);
../_images/frame_plot_subplots_layout.png

上記の例は、以下を使用する場合と同じです。

In [148]: df.plot(subplots=True, layout=(2, -1), figsize=(6, 6), sharex=False);

必要な列数 (3) は、プロットする系列の数と指定された行数 (2) から推測されます。

事前に作成した複数の軸を、ax キーワードを介してリスト型で渡すことができます。これにより、より複雑なレイアウトが可能になります。渡された軸の数は、描画されるサブプロットの数と同じでなければなりません。

ax キーワードを介して複数の軸を渡すと、layoutsharexsharey キーワードは出力に影響しません。sharex=Falsesharey=False を明示的に渡さないと、警告が表示されます。

In [149]: fig, axes = plt.subplots(4, 4, figsize=(9, 9))

In [150]: plt.subplots_adjust(wspace=0.5, hspace=0.5)

In [151]: target1 = [axes[0][0], axes[1][1], axes[2][2], axes[3][3]]

In [152]: target2 = [axes[3][0], axes[2][1], axes[1][2], axes[0][3]]

In [153]: df.plot(subplots=True, ax=target1, legend=False, sharex=False, sharey=False);

In [154]: (-df).plot(subplots=True, ax=target2, legend=False, sharex=False, sharey=False);
../_images/frame_plot_subplots_multi_ax.png

別の方法としては、特定の軸にプロットするために、Series.plot()ax 引数を渡す方法があります。

In [155]: np.random.seed(123456)

In [156]: ts = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000))

In [157]: ts = ts.cumsum()

In [158]: df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=list("ABCD"))

In [159]: df = df.cumsum()
In [160]: fig, axes = plt.subplots(nrows=2, ncols=2)

In [161]: plt.subplots_adjust(wspace=0.2, hspace=0.5)

In [162]: df["A"].plot(ax=axes[0, 0]);

In [163]: axes[0, 0].set_title("A");

In [164]: df["B"].plot(ax=axes[0, 1]);

In [165]: axes[0, 1].set_title("B");

In [166]: df["C"].plot(ax=axes[1, 0]);

In [167]: axes[1, 0].set_title("C");

In [168]: df["D"].plot(ax=axes[1, 1]);

In [169]: axes[1, 1].set_title("D");
../_images/series_plot_multi.png

エラーバーを使用したプロット#

DataFrame.plot()Series.plot() では、エラーバーを使用したプロットがサポートされています。

水平方向と垂直方向のエラーバーは、plot()xerr および yerr キーワード引数に指定できます。エラー値は、さまざまな形式で指定できます。

  • プロットする DataFramecolumns 属性と一致する列名を持つエラーの DataFrame または Seriesname 属性と一致する DataFrame または dict として。

  • プロットする DataFrame のどの列がエラー値を含むかを示す str として。

  • 生の値 (listtuple、または np.ndarray) として。プロットする DataFrame/Series と同じ長さでなければなりません。

生のデータから標準偏差を含むグループ平均を簡単にプロットする1つの方法の例を以下に示します。

# Generate the data
In [170]: ix3 = pd.MultiIndex.from_arrays(
   .....:     [
   .....:         ["a", "a", "a", "a", "a", "b", "b", "b", "b", "b"],
   .....:         ["foo", "foo", "foo", "bar", "bar", "foo", "foo", "bar", "bar", "bar"],
   .....:     ],
   .....:     names=["letter", "word"],
   .....: )
   .....: 

In [171]: df3 = pd.DataFrame(
   .....:     {
   .....:         "data1": [9, 3, 2, 4, 3, 2, 4, 6, 3, 2],
   .....:         "data2": [9, 6, 5, 7, 5, 4, 5, 6, 5, 1],
   .....:     },
   .....:     index=ix3,
   .....: )
   .....: 

# Group by index labels and take the means and standard deviations
# for each group
In [172]: gp3 = df3.groupby(level=("letter", "word"))

In [173]: means = gp3.mean()

In [174]: errors = gp3.std()

In [175]: means
Out[175]: 
                data1     data2
letter word                    
a      bar   3.500000  6.000000
       foo   4.666667  6.666667
b      bar   3.666667  4.000000
       foo   3.000000  4.500000

In [176]: errors
Out[176]: 
                data1     data2
letter word                    
a      bar   0.707107  1.414214
       foo   3.785939  2.081666
b      bar   2.081666  2.645751
       foo   1.414214  0.707107

# Plot
In [177]: fig, ax = plt.subplots()

In [178]: means.plot.bar(yerr=errors, ax=ax, capsize=4, rot=0);
../_images/errorbar_example.png

非対称エラーバーもサポートされていますが、この場合は生のエラー値を指定する必要があります。N 個の長さの Series の場合、下限と上限(または左と右)のエラーを示す 2xN 配列を指定する必要があります。MxNDataFrame の場合、非対称エラーは Mx2xN 配列で指定する必要があります。

非対称エラーバーを使用して最小/最大範囲をプロットする1つの方法の例を以下に示します。

In [179]: mins = gp3.min()

In [180]: maxs = gp3.max()

# errors should be positive, and defined in the order of lower, upper
In [181]: errors = [[means[c] - mins[c], maxs[c] - means[c]] for c in df3.columns]

# Plot
In [182]: fig, ax = plt.subplots()

In [183]: means.plot.bar(yerr=errors, ax=ax, capsize=4, rot=0);
../_images/errorbar_asymmetrical_example.png

テーブルのプロット#

matplotlib テーブルを使用したプロットは、table キーワードを使用して DataFrame.plot()Series.plot() でサポートされるようになりました。table キーワードには、boolDataFrame、または Series を指定できます。テーブルを描画する簡単な方法は、table=True を指定することです。データは、matplotlib のデフォルトのレイアウトに合わせて転置されます。

In [184]: np.random.seed(123456)

In [185]: fig, ax = plt.subplots(1, 1, figsize=(7, 6.5))

In [186]: df = pd.DataFrame(np.random.rand(5, 3), columns=["a", "b", "c"])

In [187]: ax.xaxis.tick_top()  # Display x-axis ticks on top.

In [188]: df.plot(table=True, ax=ax);
../_images/line_plot_table_true.png

また、異なる DataFrame または Seriestable キーワードに渡すことができます。データは、print メソッドに表示されるように描画されます(自動的に転置されません)。必要に応じて、以下の例のように手動で転置する必要があります。

In [189]: fig, ax = plt.subplots(1, 1, figsize=(7, 6.75))

In [190]: ax.xaxis.tick_top()  # Display x-axis ticks on top.

In [191]: df.plot(table=np.round(df.T, 2), ax=ax);
../_images/line_plot_table_data.png

DataFrame または Series からテーブルを作成し、matplotlib.Axes インスタンスに追加するヘルパー関数 pandas.plotting.table も存在します。この関数は、matplotlib のtable が持つキーワードを受け入れることができます。

In [192]: from pandas.plotting import table

In [193]: fig, ax = plt.subplots(1, 1)

In [194]: table(ax, np.round(df.describe(), 2), loc="upper right", colWidths=[0.2, 0.2, 0.2]);

In [195]: df.plot(ax=ax, ylim=(0, 2), legend=None);
../_images/line_plot_table_describe.png

**注記:** さらなる装飾のために、axes.tables プロパティを使用して、軸上のテーブルインスタンスを取得できます。詳細はmatplotlib テーブルのドキュメントを参照してください。

カラーマップ#

多数の列をプロットする場合、デフォルトの色が繰り返されるため、一部の系列を区別するのが困難になる可能性があります。これを解決するために、DataFrame プロットでは、colormap 引数の使用がサポートされています。この引数には、Matplotlib のカラーマップ、または Matplotlib に登録されているカラーマップの名前を表す文字列を指定できます。デフォルトの matplotlib カラーマップの視覚化はこちらにあります。

matplotlib は線ベースのプロットでカラーマップを直接サポートしていないため、色は DataFrame の列数によって決定される均等な間隔に基づいて選択されます。背景色については考慮されていないため、一部のカラーマップでは、見にくい線になる場合があります。

cubehelix カラーマップを使用するには、colormap='cubehelix' を渡します。

In [196]: np.random.seed(123456)

In [197]: df = pd.DataFrame(np.random.randn(1000, 10), index=ts.index)

In [198]: df = df.cumsum()

In [199]: plt.figure();

In [200]: df.plot(colormap="cubehelix");
../_images/cubehelix.png

または、カラーマップ自体を渡すこともできます。

In [201]: from matplotlib import cm

In [202]: plt.figure();

In [203]: df.plot(colormap=cm.cubehelix);
../_images/cubehelix_cm.png

カラーマップは、棒グラフなどの他のプロットタイプにも使用できます。

In [204]: np.random.seed(123456)

In [205]: dd = pd.DataFrame(np.random.randn(10, 10)).map(abs)

In [206]: dd = dd.cumsum()

In [207]: plt.figure();

In [208]: dd.plot.bar(colormap="Greens");
../_images/greens.png

並列座標チャート

In [209]: plt.figure();

In [210]: parallel_coordinates(data, "Name", colormap="gist_rainbow");
../_images/parallel_gist_rainbow.png

アンドリュース曲線チャート

In [211]: plt.figure();

In [212]: andrews_curves(data, "Name", colormap="winter");
../_images/andrews_curve_winter.png

Matplotlib を使用した直接プロット#

状況によっては、特定の種類のグラフやカスタマイズがpandasで(まだ)サポートされていない場合など、matplotlibを使用して直接グラフを作成する方が好ましい、あるいは必要となる場合があります。SeriesおよびDataFrameオブジェクトは配列のように動作するため、明示的なキャストなしでmatplotlib関数に直接渡すことができます。

pandasは、日付インデックスを認識するフォーマッタとロケータを自動的に登録し、matplotlibで使用可能な事実上すべてのグラフの種類に日付と時刻のサポートを拡張します。このフォーマットは、pandasを使用してプロットした場合と同じレベルの洗練さを提供しませんが、多数の点をプロットする場合には高速になる可能性があります。

In [213]: np.random.seed(123456)

In [214]: price = pd.Series(
   .....:     np.random.randn(150).cumsum(),
   .....:     index=pd.date_range("2000-1-1", periods=150, freq="B"),
   .....: )
   .....: 

In [215]: ma = price.rolling(20).mean()

In [216]: mstd = price.rolling(20).std()

In [217]: plt.figure();

In [218]: plt.plot(price.index, price, "k");

In [219]: plt.plot(ma.index, ma, "b");

In [220]: plt.fill_between(mstd.index, ma - 2 * mstd, ma + 2 * mstd, color="b", alpha=0.2);
../_images/bollinger.png

プロットバックエンド#

pandasは、サードパーティのプロットバックエンドで拡張できます。主な考え方は、ユーザーがMatplotlibベースのデフォルトとは異なるプロットバックエンドを選択できるようにすることです。

これは、plot関数でbackend引数として'backend.module'を渡すことで実行できます。例:

>>> Series([1, 2, 3]).plot(backend="backend.module")

あるいは、このオプションをグローバルに設定することもできます。そうすれば、各plot呼び出しでキーワードを指定する必要はありません。例:

>>> pd.set_option("plotting.backend", "backend.module")
>>> pd.Series([1, 2, 3]).plot()

または

>>> pd.options.plotting.backend = "backend.module"
>>> pd.Series([1, 2, 3]).plot()

これはほぼ次と同等です。

>>> import backend.module
>>> backend.module.plot(pd.Series([1, 2, 3]))

その後、バックエンドモジュールは、他の可視化ツール(Bokeh、Altair、hvplotなど)を使用してグラフを生成できます。pandasのバックエンドを実装するいくつかのライブラリは、エコシステムページにリストされています。

開発者向けガイドはhttps://pandas.dokyumento.jp/docs/dev/development/extending.html#plotting-backendsにあります。