【スタイル付き出力】Pandas Styler:format・background_gradient・bar・highlight_max・to_html
データ分析の最終ステップはプレゼンテーションです。数字そのものに語らせましょう。Pandas StylerはDataFrameをカラフルなレポートに変えます。売上が高いものは緑、低いものは赤、進行状況バーをインラインで埋め込み、最大値をハイライト表示します。Excelで色を手作業で選ぶ必要はありません。Pandasがすべて自動で処理してくれます。
⚠️ 注意: 以下のコードはローカルのPython環境で実行してください。
1. 学習内容
- ❶ Stylerオブジェクト
- ❷ format による書式設定
- ❸ background_gradient ヒートマップハイライト
- ❹ bar インライン棒グラフ
- ❺ highlight 条件付きマーキング
2. キャロルの売上レポートを美しくする
(1) 課題:プレーンな数値レポートは直感的でない
キャロルの月次売上レポートは数字ばかりで、上司は何が高くて何が低いのかわかりません:
PYTHON
import pandas as pd
import numpy as np
np.random.seed(42)
df = pd.DataFrame({
'region': ['North', 'South', 'East', 'West'],
'sales': [5200, 3100, 4800, 2900],
'profit': [1560, 620, 1440, 435],
'margin': [0.30, 0.20, 0.30, 0.15]
})
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して一緒に進めてください。実際の値はpandasのバージョンによって若干異なる場合があります。
(2) 解決策:Stylerによるワンラインの装飾
▶ サンプル:Stylerの基本
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して一緒に進めてください。実際の値はpandasのバージョンによって若干異なる場合があります。
:Stylerの基本(難易度 ⭐)
PYTHON
import pandas as pd
import numpy as np
np.random.seed(42)
df = pd.DataFrame({
'region': ['North', 'South', 'East', 'West'],
'sales': [5200, 3100, 4800, 2900],
'profit': [1560, 620, 1440, 435],
'margin': [0.30, 0.20, 0.30, 0.15]
})
# スタイルメソッドをチェーン
styled = (df.style
.format({'sales': '${:,.0f}', 'profit': '${:,.0f}', 'margin': '{:.1%}'})
.background_gradient(subset=['sales'], cmap='RdYlGn')
.highlight_max(subset=['profit'], color='lightgreen')
)
# Jupyterではstyledでスタイル付きテーブルが表示される
# styled.to_html('report.html') でエクスポート
print("Styled table created!")
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して一緒に進めてください。実際の値はpandasのバージョンによって若干異なる場合があります。
3. Stylerオブジェクト
(1) df.styleはStylerを返す
▶ サンプル:Stylerの基本操作
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して一緒に進めてください。実際の値はpandasのバージョンによって若干異なる場合があります。
:Stylerの基本操作(難易度 ⭐)
PYTHON
import pandas as pd
import numpy as np
np.random.seed(42)
df = pd.DataFrame({
'product': ['A', 'B', 'C', 'D', 'E'],
'price': [29.99, 99.99, 149.99, 499.99, 9.99],
'stock': [50, 120, 80, 35, 200],
'rating': [4.5, 4.2, 3.8, 4.8, 4.0]
})
# df.styleはStylerを返す(DataFrameではない!)
styler = df.style
print(type(styler)) # pandas.io.formats.style.Styler
# 複数のスタイルをチェーン
result = (df.style
.format({'price': '${:.2f}', 'rating': '{:.1f}/5.0'})
.set_caption('Product Catalog')
.set_properties(**{'text-align': 'center'}, subset=['price', 'rating'])
)
# resultはJupyterでレンダリングされる
# Stylerは元のDataFrameを変更しない
print(df['price'].dtype) # 変わらずfloat64のまま
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して一緒に進めてください。実際の値はpandasのバージョンによって若干異なる場合があります。
4. format による書式設定
▶ サンプル:formatの数値フォーマット
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して一緒に進めてください。実際の値はpandasのバージョンによって若干異なる場合があります。
:formatの数値フォーマット(難易度 ⭐)
PYTHON
import pandas as pd
import numpy as np
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'salary': [75000.50, 92000.75, 68000.25],
'bonus': [0.15, 0.20, 0.10],
'performance': [4.567, 3.891, 4.123]
})
styled = df.style.format({
'salary': '${:,.2f}', # $75,000.50
'bonus': '{:.0%}', # 15%
'performance': '{:.1f}/5.0' # 4.6/5.0
})
# すべての数値列をフォーマット
styled2 = df.style.format(precision=2) # すべて小数点以下2桁
# 桁区切り
styled3 = df.style.format({'salary': '{:,.0f}'}) # 75,001
# カスタムフォーマッタ関数
styled4 = df.style.format({
'salary': lambda x: f'${x:,.0f}'
})
print("Formatted tables created!")
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して一緒に進めてください。実際の値はpandasのバージョンによって若干異なる場合があります。
5. background_gradient ヒートマップハイライト
▶ サンプル:background_gradientヒートマップ
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して一緒に進めてください。実際の値はpandasのバージョンによって若干異なる場合があります。
:background_gradientヒートマップ(難易度 ⭐⭐)
PYTHON
import pandas as pd
import numpy as np
np.random.seed(42)
df = pd.DataFrame({
'region': ['North', 'South', 'East', 'West'],
'Q1': [5200, 3100, 4800, 2900],
'Q2': [5800, 3400, 5100, 3100],
'Q3': [6100, 3800, 5600, 3500],
'Q4': [6500, 4100, 5900, 3800]
}).set_index('region')
# ヒートマップ:RdYlGn(赤-黄-緑)
styled = df.style.background_gradient(cmap='RdYlGn')
# サブセット:特定の列のみ
styled2 = df.style.background_gradient(
subset=['Q1', 'Q4'],
cmap='Blues',
vmin=2000, vmax=7000
)
# 列ごとのグラデーション(各列を独立してスケール)
styled3 = df.style.background_gradient(cmap='YlOrRd', axis=0)
# 行ごとのグラデーション(各行を独立してスケール)
styled4 = df.style.background_gradient(cmap='YlOrRd', axis=1)
print("Heatmap styles created!")
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して一緒に進めてください。実際の値はpandasのバージョンによって若干異なる場合があります。
(1) よく使われるcmap
| cmap | 効果 | 用途 |
|---|---|---|
| RdYlGn | 赤 → 黄 → 緑 | 高いほど良い |
| RdYlBu | 赤 → 黄 → 青 | 発散型 |
| Blues | 明るい → 濃い青 | 単調増加 |
| YlOrRd | 黄 → オレンジ → 赤 | 高いほど悪い |
| coolwarm | 青 → 赤 | 偏差 |
6. bar インライン棒グラフ
▶ サンプル:barインライン棒グラフ
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して一緒に進めてください。実際の値はpandasのバージョンによって若干異なる場合があります。
:barインライン棒グラフ(難易度 ⭐⭐)
PYTHON
import pandas as pd
import numpy as np
np.random.seed(42)
df = pd.DataFrame({
'product': ['A', 'B', 'C', 'D', 'E'],
'sales': [5200, 3100, 4800, 2900, 6500],
'target': [5000, 4000, 5000, 3000, 6000]
})
# セル内の棒グラフ
styled = df.style.bar(
subset=['sales'],
color='lightblue',
vmin=0, vmax=7000
)
# 達成率:棒グラフが目標に対する割合を表示
df['achievement'] = (df['sales'] / df['target'] * 100).round(1)
styled2 = df.style.bar(
subset=['achievement'],
color=['#ff6b6b', '#51cf66'], # 赤 < 100%、緑 >= 100%
vmin=0, vmax=150
)
print("Bar chart styles created!")
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して一緒に進めてください。実際の値はpandasのバージョンによって若干異なる場合があります。
7. highlight 条件付きマーキング
▶ サンプル:highlight_max/min/null
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して一緒に進めてください。実際の値はpandasのバージョンによって若干異なる場合があります。
:highlight_max/min/null(難易度 ⭐⭐)
PYTHON
import pandas as pd
import numpy as np
np.random.seed(42)
df = pd.DataFrame({
'product': ['A', 'B', 'C', 'D', 'E'],
'price': [29.99, 99.99, 149.99, 499.99, 9.99],
'stock': [50, 120, 80, 35, np.nan],
'rating': [4.5, 4.2, 3.8, 4.8, 4.0]
})
# 列ごとの最大値をハイライト
styled = df.style.highlight_max(
subset=['price', 'stock', 'rating'],
color='lightgreen'
)
# 最小値をハイライト
styled2 = df.style.highlight_min(
subset=['price', 'rating'],
color='lightcoral'
)
# NaN値をハイライト
styled3 = df.style.highlight_null(color='yellow')
# カスタム:在庫不足(< 40)をハイライト
def highlight_low_stock(val):
color = 'red' if val < 40 else ''
return f'background-color: {color}'
styled4 = df.style.applymap(highlight_low_stock, subset=['stock'])
# 注意:Pandas 2.xではapplymapはmapに名称変更された
# styled4 = df.style.map(highlight_low_stock, subset=['stock'])
print("Highlight styles created!")
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して一緒に進めてください。実際の値はpandasのバージョンによって若干異なる場合があります。
8. 総合例:売上レポートのスタイリング
(5) ▶ スタイリングチェーンのワークフロー
graph LR
A[df.style] --> B[format 書式設定]
B --> C[background_gradient ヒートマップ]
C --> D[bar インライン棒グラフ]
D --> E[highlight 条件付きマーキング]
E --> F[set_caption タイトル]
F --> G[to_html / to_excel エクスポート]
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して一緒に進めてください。実際の値はpandasのバージョンによって若干異なる場合があります。
▶ サンプル:総合的なレポートスタイリング
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して一緒に進めてください。実際の値はpandasのバージョンによって若干異なる場合があります。
:総合的なレポートスタイリング(難易度 ⭐⭐⭐)
PYTHON
import pandas as pd
import numpy as np
# ============================================
# 総合例:売上レポートのスタイリング
# format → gradient → bar → highlight → export
# ============================================
np.random.seed(42)
df = pd.DataFrame({
'region': ['North', 'South', 'East', 'West', 'Central'],
'revenue': [520000, 310000, 480000, 290000, 410000],
'cost': [364000, 248000, 336000, 246500, 307500],
'profit': [156000, 62000, 144000, 43500, 102500],
'margin': [0.30, 0.20, 0.30, 0.15, 0.25],
'growth': [0.12, -0.05, 0.08, -0.10, 0.15],
'customers': [1200, 850, 1100, 680, 950]
}).set_index('region')
# 複数スタイルのチェーン
styled = (df.style
.format({
'revenue': '${:,.0f}',
'cost': '${:,.0f}',
'profit': '${:,.0f}',
'margin': '{:.1%}',
'growth': '{:+.1%}',
'customers': '{:,}'
})
.background_gradient(subset=['margin'], cmap='RdYlGn', vmin=0, vmax=0.4)
.bar(subset=['customers'], color='lightblue', vmin=0)
.highlight_max(subset=['profit'], color='lightgreen')
.highlight_min(subset=['profit'], color='lightcoral')
.set_caption('2024 Regional Sales Report')
.set_properties(**{'text-align': 'right'}, subset=['revenue', 'cost', 'profit'])
)
# エクスポート
# styled.to_html('report.html')
# styled.to_excel('report.xlsx', engine='openpyxl')
print("Full styled report created!")
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して一緒に進めてください。実際の値はpandasのバージョンによって若干異なる場合があります。
❓ よくある質問
Q Stylerはデータを変更しますか?
A いいえ。Stylerは表示にのみ影響し、元のDataFrameのデータは変更されません。df.styleは「表示層」の装飾であり、「データ層」には一切触れません。フォーマット後もdf['salary']は文字列ではなくfloat64のままです。同じDataFrameからスタイルの異なる複数のStylerを安全に作成できます。
Q background_gradientのcmapはどう選べばいいですか?
A 高いほど良い場合はRdYlGn(赤 → 緑)、高いほど悪い場合はYlOrRd(黄 → 赤)、発散型の偏差にはcoolwarm(青 → 赤)、単調増加にはBluesを使います。cmap選びの原則は、色の直感がビジネス上の意味と一致することです。決める前にJupyterで効果を確認しましょう。
Q subsetで範囲を指定するには?
A 3つの方法があります。① 列名のリスト
subset=['sales', 'profit']、② スライス subset=pd.IndexSlice[:, 'Q1':'Q4']、③ 条件フィルタ subset=pd.IndexSlice[df['sales'] > 3000, :]。最も一般的なのは列名のリストです。Q to_htmlで日本語が文字化けする場合は?
A エンコーディングを指定します。
styled.to_html(encoding='utf-8')。ファイルに書き込む場合は with open('report.html', 'w', encoding='utf-8') as f: f.write(styled.to_html()) を使います。HTMLファイルに <meta charset="utf-8"> が宣言されていることを確認してください。Q スタイルをExcelにエクスポートできますか?
A できます。
styled.to_excel('report.xlsx', engine='openpyxl')。色と書式はExcelに保持されます。ただし、一部のスタイルは完全には一致しない場合があります(たとえばインライン棒グラフはExcelでは条件付き書式になります)。pip install openpyxl が必要です。Q applymapとmapの違いは何ですか?
A Pandas 2.xでは、Styler.applymapはStyler.mapに名称変更されました。機能は同じで、各セルにスタイル関数を適用します。applyは行/列単位(axisパラメータ)で動作し、mapはセル単位で動作します。新しいバージョンではmapを使うだけで十分です。
Q 複数のスタイルをチェーンするには?
A StylerのメソッドはStylerオブジェクトを返すため、チェーンが自然にサポートされます。
df.style.format({...}).background_gradient(...).bar(...).highlight_max(...)。上から下へ適用され、後のスタイルが競合する前のスタイルを上書きします。推奨順序は format → gradient → bar → highlight → set_caption です。📖 まとめ
- df.styleはStylerオブジェクトを返す。表示にのみ影響し、データは変更しない
- formatは数値をフォーマットする:通貨(${:,.0f})/ パーセント({:.0%})/ 精度(precision)
- background_gradientヒートマップハイライト:cmapで色を選び、subsetで範囲を選び、axisで方向を制御する
- barインライン棒グラフ:colorは単色または2色、vmin/vmaxで範囲を制御する
- highlight_max/min/nullで条件付きハイライト、map/applyでカスタム条件
- チェーン:format → gradient → bar → highlight → caption
- to_html/to_excelでスタイル付きレポートをエクスポート
📝 練習問題
- 基礎(難易度 ⭐):salary/bonus列を持つDataFrameを作成し、formatで通貨とパーセントにフォーマットして、highlight_maxで最高給与をマークしてください。
- 中級(難易度 ⭐⭐):四半期売上のDataFrame(行 = 地域、列 = Q1-Q4)を作成し、background_gradient(cmap='RdYlGn')ヒートマップ + barインライン棒グラフ + formatの桁区切りフォーマットを組み合わせてください。
- 挑戦(難易度 ⭐⭐⭐):5地域の売上レポート(revenue/cost/profit/margin/growth)をシミュレートし、5ステップのスタイリングチェーンを完成させてください。複数フォーマットのformat → gradient(margin) → bar(customers) → highlight_max(profit) → to_htmlエクスポート。



