pandasのstyleでテーブル出力をわかりやすくする
JupyterにおけるPandasのテーブルデータの出力に色をつけてわかりやすくしたい。
そのためには、pandasのstyle周りをいじれば良いみたい。
基本的にドキュメントのUser Guideベースで書いていく。
styleのいじり方は2つあり、1つは組み込みメソッドをそのまま使うやり方。もう1つは自分でCSSを指定する関数を定めてapply
かapplymap
を適用する(前者は値に、後者は行/列に適用)。
データはテキトーに以下を使う。
import pandas as pd import numpy as np np.random.seed(24) df = pd.DataFrame({'A': np.linspace(1, 10, 10)}) df = pd.concat([df, pd.DataFrame(np.random.randn(10, 4), columns=list('BCDE'))], axis=1) df.iloc[3, 3] = np.nan df.iloc[0, 2] = np.nan df.head()
Builtin styles
一般的によく使うものに対して組み込みでメソッドがあるのでそれをそのまま使うやり方。
Nullの背景色指定
style.highlight_null()
でNullの背景色を指定できる。
df.style.highlight_null(null_color='red')
連続値のグラデーション背景
連続値に対してグラデーションで背景指定。
background_gradient
で指定する。
引数cmap
に対してカラーマップを指定することでグラデーションを指定する。
カラーマップは Matplotlib colormapやseabornのカラーマップ(パレットが使える
df.style.background_gradient(cmap='viridis', low=.5, high=0) # Matplotlib colormapのviridisにして、0.0 - 5.0のレンジでグラデーション
import seaborn as sns cm = sns.light_palette("green", as_cmap=True) # seabornのlight_paletteで緑グラデーションオブジェクトを作成 df.style.background_gradient(background_gradient=cm) # 緑グラデーションオブジェクトの適用
ちなみに、どうやらbackground_gradient
のcmap
はMatplotlib colormapだとnan含めて色づけられるがseabornカラーマップだと最小値と同じ色になるっぽい?別の色を指定したい場合はhighlight_null
でnan背景を上書きする。
matplot_color = df.style.background_gradient(cmap='viridis') # Matplotlib colormap cm = sns.light_palette("green", as_cmap=True) sns_color = df.style.background_gradient(cmap=cm) # Seaborn colorpalette sns_color_nan = df.style.background_gradient(cmap=cm).highlight_null('black') # Seaborn colorpalette + nanを黒にする display(matplot_color,sns_color,sns_color_nan)
最大最小値のハイライト
highlight_max
で最大値を、highlight_min
で最小値をハイライトする。
pandas.io.formats.style.Styler.highlight_min — pandas 1.0.3 documentation
df.style.highlight_max(axis=0,color='red') # 列毎の最大値
df.style.highlight_max(subset='B', color='grey') # A列の最大値
df.style.highlight_min(axis=None,color='red') # 全体の最小値
値のフォーマット
format
で値のフォーマットを変えられる。
df.style.format("{:.2%}") # 2桁でパーセント表示
df.style.format({"B": lambda x: "±{:.2f}".format(abs(x))}) # B列に「±」⊥をつけて2桁表示
背景に棒グラフを表示
値をもとに、背景に棒グラフを表示する。
引数align
はleft, zero, midから選択する。それぞれ、
- left : 最小値が左端になる
- zero : 0を中央として負の数を中央より左、正の数を中央より右に表示する
- mid : 正負が混じっているときは(最大値-最小値)/2を中央にする。全てが正の数(負の数)のときは左端(右端)を0とする。
となる。
df.style.bar(subset=['A', 'B'], align='zero', color=['#d65f5f', '#5fba7d'])
文字精度
set_precision
でx桁表示。
df.style.set_precision(2)
CSSで装飾
背景色・文字色・枠線などの色はset_properties
を使う。
辞書でCSS形式で渡しても良いし、直接引数にしてもよいがドキュメントにあまり例が載ってないので何が使えて使えないのか正直よくわからん。
なお、subset
で列を指定することも可能。
# 辞書での指定 df.style.set_properties(**{'background-color': 'black', # 背景 'color': 'lawngreen', # 文字色 'border-color': 'white', # 枠の色っぽいが、変わってない? 'align':'left'}) # 文字の揃える位置っぽいが、変わってない?
Building styles
自分でCSSを指定する関数を定めてapplymap
かapply
を適用する(前者は行/列単位、後者は値単位。
CSSを使ったことないのでざっくりと説明。
以下では、渡された値を判定して、負の数で赤、正の数で黒となるCSS指定を返す関数を用いる。
これをapplymap
で値毎に判定することで、各値の色を変える。
def color_negative_red(val): """ Takes a scalar and returns a string with the css property `'color: red'` for negative strings, black otherwise. """ color = 'red' if val < 0 else 'black' return 'color: %s' % color # 返り値はCSS文字列 df.style.applymap(color_negative_red)
以下は、渡されたSeriesの中での最大値を黄色で表示する関数を用いてapply
を適用している。
def highlight_max(s): ''' highlight the maximum in a Series yellow. ''' is_max = s == s.max() return ['background-color: yellow' if v else '' for v in is_max] df.style.apply(highlight_max) # axisはデフォルトは0なので列に対して適用。1だと行、Noneだと全体。
set_table_styles
に直接入れても良い。
styles = [ dict(selector="th", props=[("font-size", "150%"), ("text-align", "center")]) ] df.style.set_table_styles(styles)
複合
なお、これらを組み合わせることができる。
np.random.seed(25) cmap = cmap=sns.diverging_palette(5, 250, as_cmap=True) bigdf = pd.DataFrame(np.random.randn(20, 25)).cumsum() def magnify(): return [dict(selector="th", props=[("font-size", "4pt")]), dict(selector="td", props=[('padding', "0em 0em")]), dict(selector="th:hover", props=[("font-size", "12pt")]), dict(selector="tr:hover td:hover", props=[('max-width', '200px'), ('font-size', '12pt')]) ] bigdf.style\ .background_gradient(cmap, axis=1)\ .set_properties(**{'max-width': '80px', 'font-size': '1pt'})\ .set_caption("Hover to magnify")\ .set_precision(2)\ .set_table_styles(magnify())\ .highlight_null('black')
その他参考
以下のスライドがどちゃくそわかりやすかったしよくまとまっている。