Python Jupyter + pandas で DataFrame 表示をカスタマイズする
先日 pandas
v0.17.1 がリリースされた。v0.17.0 に対するバグフィックスがメインだが、以下の追加機能もあるため その内容をまとめたい。
HTML 表示のカスタマイズ
Jupyer
上では pandas
の DataFrame
は自動的に HTML として描画される。この HTML に対して、さまざまな CSS を柔軟に設定できるようになった。
このエントリでは、添付した公式ドキュメントとは少し違う例を記載する。
重要 公式ドキュメントにも記載がされているが v0.17.1 時点で開発中 / Experimental な追加のため、今後 破壊的な変更が発生する可能性がある。ご要望やお気づきの点があれば GitHub issue か @ ください。
以降、Jupyter
にて実行する。まず DataFrame
を作成して表示する。
import pandas as pd import numpy as np np.__version__ # '1.10.1' pd.__version__ # u'0.17.1' np.random.seed(1) df = pd.DataFrame({'name': list('abcdefg'), 'values1': np.random.randn(7), 'values2': np.random.randn(7)}) df
v0.17.0 にて DataFrame
に DataFrame.style
アクセサが追加され、これを経由して種々のカスタマイズができる。例えば、各セルの値に応じてカラーマップを適用するには Styler.background_gradient()
。
type(df.style) # pandas.core.style.Styler df.style.background_gradient(cmap='winter')
カラーマップの一部範囲の色のみ利用する場合は low
, high
キーワードで範囲を指定する。
df.style.background_gradient(cmap='winter', low=2.)
特定の列にのみ Styler
を適用する場合は subset
キーワード。
df.style.background_gradient(cmap='winter', low=2., subset=['values1'])
さらに特定のセルにのみ適用する場合は 対象セルを指定する pd.IndexSlice
インスタンスを subset
として指定する。
pd.IndexSlice[2:5, ['values1']] # (slice(2, 5, None), ['values1']) # .loc に渡した場合は対象セルのみをスライス df.loc[pd.IndexSlice[2:5, ['values1']]]
df.style.background_gradient(cmap='winter', low=2., subset=pd.IndexSlice[2:5, ['values1']])
Styler
は background_gradient
以外にも 以下のようなメソッドをもつ。
Styler.highlight_max()
: 列もしくは行の最大値を指定して色分け。Styler.highlight_min()
: 列もしくは行の最小値を指定して色分け。Styler.highlight_null()
:NaN
を指定して色分け。Styler.background_gradient()
: 上述。Styler.bar()
: 各セルの値に応じて棒グラフのように背景色表示。
df.iloc[1, 1] = np.nan df.style.highlight_null()
さらに、Styler.set_properties
を利用すると任意の CSS を全セルに対して適用できる。数値以外のセルを色分けするにはこれを使えばよい。
df.style.set_properties(**{'background-color': '#00ff7f'})
また、Styler
はチェインできる。
(df.style. set_properties(**{'background-color': '#00ff7f'}). background_gradient(cmap='winter', low=2.). highlight_null())
より柔軟な条件分けのため、 Styler
は .apply
系のメソッドも持つ。使い方は通常の DataFrame.apply
や .applymap
と同じだが、値そのものではなく CSS を返す関数を適用する。
Styler.applymap
: 各セルに対して CSS を返す関数を適用 (関数への入力はスカラー)。Styler.apply
: 各列もしくは各行に対して CSS を返す関数を適用 (関数への入力は 各列/各行の値からなるSeries
)。
参考 Python pandas データのイテレーションと関数適用、pipe - StatsFragments
セルの値が 0 より小さい場合は 赤 / 太字で表示する場合は Styler.applymap
。
def highlight_negative(val): if val < 0: return 'color: {0}; font-weight: bold'.format('red') else: return 'color: {0}'.format('black') df.style.applymap(highlight_negative)
各行について、values1
列の値が values2
列の値より大きいときに values1
列のみ 赤背景で表示したい。行ごとに関数を適用するため、axis=1
を指定する。highlight_values1
関数が返す リストの各要素が、各列に適用される CSS に対応している。
def highlight_values1(s): if s['values1'] > s['values2']: # return ['', 'background-color: red', ''] else: # スタイル変更しない場合は空の文字列のリストを返す return [''] * len(s) df.style.apply(highlight_values1, axis=1)
最後に、Jupyter
の widget と組み合わせることで動的なスタイル変更ができる。以下ではスライドバーの位置によって フォントの大きさを変更している。
from IPython.html import widgets @widgets.interact def f(s=(5, 30)): return (df.style.background_gradient('winter', low=2.).set_properties(**{'font-size': '{0}px'.format(s)}))
Jupyter
以外に 同様の出力を HTML として埋め込みたい場合は、Styler.render()
を利用する。
style = df.style.background_gradient('winter', low=2.) style.render() # 略 (HTML が文字列として出力される)
ピボットテーブル + グラフ表示
また Jupyter
上での DataFrame
の扱いに関連して、データそのものを GUI でインタラクティブに操作 / グラフ表示ができるpivottablejs
というパッケージがある。
まとめ
pandas
v0.17.1 で追加された DataFrame
の HTML 表示のカスタマイズ方法について記載した。
Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理
- 作者: Wes McKinney,小林儀匡,鈴木宏尚,瀬戸山雅人,滝口開資,野上大介
- 出版社/メーカー: オライリージャパン
- 発売日: 2013/12/26
- メディア: 大型本
- この商品を含むブログ (11件) を見る