グラフによる可視化#
注記
以下の例では、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();

インデックスが日付で構成されている場合、上記のように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();

plot()
のx
とy
キーワードを使用して、ある列を別の列に対してプロットできます。
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");

注記
より詳細なフォーマットとスタイルのオプションについては、下記のフォーマットを参照してください。
その他のプロット#
プロットメソッドでは、デフォルトの折れ線グラフ以外のいくつかのプロットスタイルを使用できます。これらのメソッドは、plot()
のkind
キーワード引数として指定でき、以下が含まれます。
例えば、棒グラフは次のように作成できます。
In [14]: plt.figure();
In [15]: df.iloc[5].plot(kind="bar");

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");

DataFrameのplot.bar()
メソッドを呼び出すと、複数の棒グラフが作成されます。
In [21]: df2 = pd.DataFrame(np.random.rand(10, 4), columns=["a", "b", "c", "d"])
In [22]: df2.plot.bar();

積み上げ棒グラフを作成するには、stacked=True
を渡します。
In [23]: df2.plot.bar(stacked=True);

横棒グラフを取得するには、barh
メソッドを使用します。
In [24]: df2.plot.barh(stacked=True);

ヒストグラム#
ヒストグラムは、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);

ヒストグラムはstacked=True
を使用して積み重ねることができます。ビンサイズはbins
キーワードを使用して変更できます。
In [28]: plt.figure();
In [29]: df4.plot.hist(stacked=True, bins=20);

matplotlib hist
でサポートされている他のキーワードを渡すことができます。例えば、水平ヒストグラムと累積ヒストグラムは、orientation='horizontal'
とcumulative=True
で描画できます。
In [30]: plt.figure();
In [31]: df4["a"].plot.hist(orientation="horizontal", cumulative=True);

hist
メソッドとmatplotlibヒストグラムのドキュメントの詳細を参照してください。
ヒストグラムのプロットを行う既存のインターフェースDataFrame.hist
はまだ使用できます。
In [32]: plt.figure();
In [33]: df["A"].diff().hist();

DataFrame.hist()
は、複数のサブプロット上に列のヒストグラムをプロットします。
In [34]: plt.figure();
In [35]: df.diff().hist(color="k", alpha=0.5, bins=50);

by
キーワードを指定して、グループ化されたヒストグラムをプロットできます。
In [36]: data = pd.Series(np.random.randn(1000))
In [37]: data.hist(by=np.random.randint(0, 4, 1000), figsize=(6, 4));

さらに、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));

箱ひげ図#
箱ひげ図は、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();

Boxplot は、color
キーワードを渡すことで色付けできます。boxes
、whiskers
、medians
、caps
をキーとする dict
を渡すことができます。 dict
に一部のキーが欠けている場合、対応するアーティストにはデフォルトの色が使用されます。また、boxplot には、外れ値のスタイルを指定するための sym
キーワードがあります。
color
キーワードを介して他の型の引数を渡すと、すべての boxes
、whiskers
、medians
、caps
の色付けに matplotlib に直接渡されます。
色は描画されるすべてのボックスに適用されます。より複雑な色付けが必要な場合は、return_type を渡すことで、描画された各アーティストを取得できます。
In [42]: color = {
....: "boxes": "DarkGreen",
....: "whiskers": "DarkOrange",
....: "medians": "DarkBlue",
....: "caps": "Gray",
....: }
....:
In [43]: df.plot.box(color=color, sym="r+");

また、matplotlib boxplot
でサポートされている他のキーワードを渡すこともできます。例えば、vert=False
と positions
キーワードを使用して、水平方向およびカスタム位置の boxplot を描画できます。
In [44]: df.plot.box(vert=False, positions=[1, 4, 5, 6, 8]);

詳細は、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()

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")

複数の列でグループ化する場合と同様に、プロットする列のサブセットを渡すこともできます。
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"])

例えば、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")

boxplot
では、return_type
キーワードで戻り値の型を制御できます。有効な選択肢は {"axes", "dict", "both", None}
です。by
キーワードを使用して DataFrame.boxplot
で作成されたファセットは、出力型にも影響します。
|
ファセット |
出力型 |
---|---|---|
|
いいえ |
axes |
|
はい |
axes の 2 次元 ndarray |
|
いいえ |
axes |
|
はい |
axes の Series |
|
いいえ |
アーティストの辞書 |
|
はい |
アーティストの辞書の Series |
|
いいえ |
namedtuple |
|
はい |
namedtuple の Series |
Groupby.boxplot
は常に return_type
の Series
を返します。
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")

上記のサブプロットは、まず数値列、次に g
列の値で分割されます。サブプロットの下では、まず g
の値で、次に数値列で分割されます。
In [66]: bp = df_box.groupby("g").boxplot()

面積図#
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();

積み重ねられていないプロットを作成するには、stacked=False
を渡します。アルファ値は、特に指定がない限り 0.5 に設定されます。
In [69]: df.plot.area(stacked=False);

散布図#
DataFrame.plot.scatter()
メソッドを使用して散布図を描画できます。散布図には、x 軸と y 軸に数値列が必要です。これらは、x
と y
キーワードで指定できます。
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");

単一の axes に複数の列グループをプロットするには、ターゲット ax
を指定して plot
メソッドを繰り返します。各グループを区別するために、color
と label
キーワードを指定することをお勧めします。
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);

c
キーワードは、各点の色を指定する列の名前として渡すことができます。
In [75]: df.plot.scatter(x="a", y="b", c="c", s=50);

c
にカテゴリ列を渡すと、離散的なカラーバーが生成されます。
バージョン 1.3.0 で追加。
In [76]: df.plot.scatter(x="a", y="b", c="species", cmap="viridis", s=50);

matplotlib scatter
でサポートされている他のキーワードを渡すことができます。以下の例は、DataFrame
の列をバブルサイズとして使用するバブルチャートを示しています。
In [77]: df.plot.scatter(x="a", y="b", s=df["c"] * 200);

詳細は、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);

便利なキーワード引数は gridsize
です。これは x 方向の六角形の数を制御し、デフォルトは 100 です。gridsize
が大きいほど、より多くの小さなビンになります。
デフォルトでは、各 (x, y)
点の周りのカウントのヒストグラムが計算されます。C
と reduce_C_function
引数に値を渡すことで、代替集計を指定できます。C
は各 (x, y)
点の値を指定し、reduce_C_function
は、ビンのすべての値を単一の数字に減らす 1 つの引数の関数です(例:mean
、max
、sum
、std
)。この例では、位置は列 a
と b
で与えられ、値は列 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);

詳細は、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));

円グラフには、正方形の図形、つまり縦横比が 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));

labels
と colors
キーワードを使用して、各ウェッジのラベルと色を指定できます。
警告
ほとんどのpandasプロットは、label
引数とcolor
引数を使用します(「s」がないことに注意してください)。matplotlib.pyplot.pie()
と整合性を保つには、labels
とcolors
を使用する必要があります。
ウェッジラベルを非表示にするには、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),
....: );
....:

合計が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));

詳細は、matplotlib pie ドキュメントを参照してください。
欠損値のあるデータのプロット#
pandasは、欠損値を含むDataFrames
またはSeries
のプロットについて、実用的なアプローチを取ろうとしています。欠損値は、プロットの種類に応じて削除、省略、または補完されます。
プロットの種類 |
NaNの処理 |
---|---|
折れ線グラフ |
NaNで空白を残す |
積み上げ折れ線グラフ |
0で埋める |
棒グラフ |
0で埋める |
散布図 |
NaNを削除する |
ヒストグラム |
NaNを削除する(列方向) |
箱ひげ図 |
NaNを削除する(列方向) |
面グラフ |
0で埋める |
カーネル密度推定(KDE) |
NaNを削除する(列方向) |
ヘキサビン図 |
NaNを削除する |
円グラフ |
0で埋める |
これらのデフォルトが望ましくない場合、または欠損値の処理方法を明示的に指定したい場合は、プロットする前にfillna()
またはdropna()
を使用することを検討してください。
プロットツール#
これらの関数はpandas.plotting
からインポートでき、Series
またはDataFrame
を引数として受け取ります。
散布行列プロット#
pandas.plotting
のscatter_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");

密度プロット#
Series.plot.kde()
メソッドとDataFrame.plot.kde()
メソッドを使用して、密度プロットを作成できます。
In [95]: ser = pd.Series(np.random.randn(1000))
In [96]: ser.plot.kde();

アンドリュース曲線#
アンドリュース曲線を使用すると、サンプルの属性をフーリエ級数の係数として使用して作成された多数の曲線として、多変量データをプロットできます。詳細については、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");

平行座標#
平行座標は、多変量データをプロットするためのプロット手法です。概要については、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");

ラグプロット#
ラグプロットは、データセットまたは時系列がランダムかどうかを確認するために使用されます。ランダムデータは、ラグプロットに構造を示してはなりません。非ランダムな構造は、基礎となるデータがランダムではないことを意味します。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);

自己相関プロット#
自己相関プロットは、時系列のランダム性をチェックするために頻繁に使用されます。これは、さまざまな時間ラグでのデータ値の自己相関を計算することによって行われます。時系列がランダムな場合、そのような自己相関は、あらゆる時間ラグ分離に対してゼロに近いはずです。時系列が非ランダムな場合、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);

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

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");

プロットのフォーマット#
プロットスタイルの設定#
バージョン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");

各プロットの種類(例:line
、bar
、scatter
)について、追加の引数キーワードは対応する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);

ラベルの制御#
プロットにx軸とy軸のカスタムラベルを付けるには、xlabel
引数とylabel
引数を設定します。デフォルトでは、pandasはインデックス名をxlabelとして取得し、ylabelは空のままにします。
In [127]: df.plot();
In [128]: df.plot(xlabel="new x", ylabel="new y");

スケール#
対数スケールの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);

logx
およびloglog
キーワード引数も参照してください。
2次y軸へのプロット#
2次y軸にデータをプロットするには、secondary_y
キーワードを使用します。
In [132]: df["A"].plot();
In [133]: df["B"].plot(secondary_y=True, style="g");

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");

2次y軸にプロットされた列には、凡例に「(right)」と自動的にマークされます。自動マークをオフにするには、mark_right=False
キーワードを使用します。
In [138]: plt.figure();
In [139]: df.plot(secondary_y=["A", "B"], mark_right=False);

時系列プロットのカスタムフォーマッタ#
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();

x_compat
パラメータを使用すると、この動作を抑制できます。
In [142]: plt.figure();
In [143]: df["A"].plot(x_compat=True);

抑制するプロットが複数ある場合は、pandas.plotting.plot_params
の use
メソッドを 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")
.....:

自動日付目盛調整#
TimedeltaIndex
は現在、ネイティブの matplotlib 目盛ロケータメソッドを使用しています。 tickラベルが重なる図の場合は、matplotlib から自動日付目盛調整を呼び出すと便利です。
autofmt_xdate
メソッドとmatplotlib のドキュメントを参照してください。
サブプロット#
DataFrame
内の各 Series
は、subplots
キーワードを使用して異なる軸にプロットできます。
In [146]: df.plot(subplots=True, figsize=(6, 6));

レイアウトと複数の軸のターゲット指定の使用#
サブプロットのレイアウトは、layout
キーワードで指定できます。 (rows, columns)
を受け付けます。layout
キーワードは、hist
と boxplot
でも使用できます。入力が無効な場合は、ValueError
が発生します。
layout
で指定された rows × columns で格納できる軸の数は、必要なサブプロットの数より大きくなければなりません。レイアウトに必要な数より多くの軸を格納できる場合、空の軸は描画されません。NumPy 配列の reshape
メソッドと同様に、一方の次元を -1
にして、もう一方の次元から必要な行数または列数を自動的に計算できます。
In [147]: df.plot(subplots=True, layout=(2, 3), figsize=(6, 6), sharex=False);

上記の例は、以下を使用する場合と同じです。
In [148]: df.plot(subplots=True, layout=(2, -1), figsize=(6, 6), sharex=False);
必要な列数 (3) は、プロットする系列の数と指定された行数 (2) から推測されます。
事前に作成した複数の軸を、ax
キーワードを介してリスト型で渡すことができます。これにより、より複雑なレイアウトが可能になります。渡された軸の数は、描画されるサブプロットの数と同じでなければなりません。
ax
キーワードを介して複数の軸を渡すと、layout
、sharex
、sharey
キーワードは出力に影響しません。sharex=False
と sharey=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);

別の方法としては、特定の軸にプロットするために、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");

エラーバーを使用したプロット#
DataFrame.plot()
と Series.plot()
では、エラーバーを使用したプロットがサポートされています。
水平方向と垂直方向のエラーバーは、plot()
の xerr
および yerr
キーワード引数に指定できます。エラー値は、さまざまな形式で指定できます。
プロットする
DataFrame
のcolumns
属性と一致する列名を持つエラーのDataFrame
またはSeries
のname
属性と一致するDataFrame
またはdict
として。プロットする
DataFrame
のどの列がエラー値を含むかを示すstr
として。生の値 (
list
、tuple
、または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);

非対称エラーバーもサポートされていますが、この場合は生のエラー値を指定する必要があります。N
個の長さの Series
の場合、下限と上限(または左と右)のエラーを示す 2xN
配列を指定する必要があります。MxN
の DataFrame
の場合、非対称エラーは 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);

テーブルのプロット#
matplotlib テーブルを使用したプロットは、table
キーワードを使用して DataFrame.plot()
と Series.plot()
でサポートされるようになりました。table
キーワードには、bool
、DataFrame
、または 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);

また、異なる DataFrame
または Series
を table
キーワードに渡すことができます。データは、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);

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);

**注記:** さらなる装飾のために、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");

または、カラーマップ自体を渡すこともできます。
In [201]: from matplotlib import cm
In [202]: plt.figure();
In [203]: df.plot(colormap=cm.cubehelix);

カラーマップは、棒グラフなどの他のプロットタイプにも使用できます。
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");

並列座標チャート
In [209]: plt.figure();
In [210]: parallel_coordinates(data, "Name", colormap="gist_rainbow");

アンドリュース曲線チャート
In [211]: plt.figure();
In [212]: andrews_curves(data, "Name", colormap="winter");

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);

プロットバックエンド#
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にあります。