1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Python × matplotlib 実用Tips:plt.styleとplt.closeを正しく使う

Posted at

user:

次のような構成の pandas dataframe 形式ファイルがあります。

Index	mean	ci_lower	ci_upper
1	1.5	1.0	2.0
2	1.0	0.5	1.5
3	-1.0	-2.0	-0.5

これを入力として、indexを横軸に、meanの値を縦軸にした棒グラフを描画したfigを返り値とするPython関数を書いてください。

これをPowerPointにそのまま貼り付けても文字等が見えるようにしたいです。また、X軸のラベルは90度傾けてほしいです。ci_lowerとci_upperは信頼区間を表し、これはエラーバーとして描画してください。meanの値が正の値ならば赤色、負の値ならば青色にしてください。

assistant:

以下のPython関数は、指定された形式の pandas.DataFrame を入力として、matplotlib を使って見やすい棒グラフ(エラーバー付き)を描画し、fig オブジェクトを返します。フォントサイズや軸ラベル角度もPowerPoint貼付け時に見やすく調整済みです。


✅ 要件を満たす関数

import matplotlib.pyplot as plt
import pandas as pd

def plot_bar_with_ci(df: pd.DataFrame):
    """
    指定されたDataFrameからエラーバー付きの棒グラフを作成する。

    Args:
        df (pd.DataFrame): 'Index', 'mean', 'ci_lower', 'ci_upper' の列を含むDataFrame。

    Returns:
        matplotlib.figure.Figure: 描画された棒グラフのFigureオブジェクト。
    """
    # グラフスタイル設定(PowerPoint用にフォントサイズを大きめに)
    plt.style.use('default')
    fig, ax = plt.subplots(figsize=(8, 6))

    # インデックスとバーの高さ、エラーバーの算出
    x = df.index.astype(str)
    y = df['mean']
    yerr = [y - df['ci_lower'], df['ci_upper'] - y]

    # 色設定:正なら赤、負なら青
    colors = ['red' if val >= 0 else 'blue' for val in y]

    # 棒グラフの描画
    bars = ax.bar(x, y, yerr=yerr, capsize=5, color=colors, edgecolor='black')

    # 軸やラベルの調整
    ax.set_xlabel("Index", fontsize=14)
    ax.set_ylabel("Mean Value", fontsize=14)
    ax.set_title("Mean with Confidence Intervals", fontsize=16)
    ax.tick_params(axis='x', labelrotation=90, labelsize=12)
    ax.tick_params(axis='y', labelsize=12)
    ax.axhline(0, color='gray', linewidth=1, linestyle='--')

    # レイアウト調整(PowerPoint用)
    fig.tight_layout()
    return fig

🔧 使用例

# データ例
data = {
    'mean': [1.5, 1.0, -1.0],
    'ci_lower': [1.0, 0.5, -2.0],
    'ci_upper': [2.0, 1.5, -0.5]
}
df = pd.DataFrame(data, index=[1, 2, 3])

# グラフ生成
fig = plot_bar_with_ci(df)
plt.show()  # Jupyterなどの環境で表示

💡 補足

  • fig.tight_layout() により、PowerPointにコピペしても要素がはみ出しにくいです。
  • capsize=5 によってエラーバーの端点が視認しやすくなっています。
  • color の割り当ては mean の値に応じて赤または青に自動化しています。

必要に応じて、画像ファイルとして保存(fig.savefig("plot.png", dpi=300))すれば、PowerPoint貼付け時の品質も高く保てます。希望があれば、その保存コードも追加できます。

user:

japanize_matplotlib を使ってるにも関わらず次のようなエラーになるんですが、 fig.savefigに必要なオプションなどありますか?

/Users/maskot/streamlit-app/venv/lib/python3.10/site-packages/streamlit/elements/pyplot.py:176: UserWarning: Glyph 24112 (\N{CJK UNIFIED IDEOGRAPH-5E30}) missing from font(s) DejaVu Sans.
  fig.savefig(image, **kwargs)
/Users/maskot/streamlit-app/venv/lib/python3.10/site-packages/streamlit/elements/pyplot.py:176: UserWarning: Glyph 26376 (\N{CJK UNIFIED IDEOGRAPH-6708}) missing from font(s) DejaVu Sans.
  fig.savefig(image, **kwargs)

assistant:

japanize_matplotlib を使っていても fig.savefig() 時に「日本語(CJK文字)のグリフが見つからない」というエラー(missing from font(s) DejaVu Sans)が出るのは、Streamlitや matplotlibフォント設定を正しく継承していないか、保存時に明示していないことが原因です。


✅ 解決策まとめ

✅ 1. japanize_matplotlib を再インポートして明示的に有効化

import japanize_matplotlib

すでに実行していると思いますが、これが最初に必要です。


✅ 2. fig.savefig() 時に bbox_inches="tight" を指定

これは文字が切れる問題にも対応します(日本語に限らず推奨されます):

fig.savefig("output.png", dpi=300, bbox_inches="tight")

✅ 3. 描画前にフォントが適用されているか確認

japanize_matplotlibmatplotlib.rcParams に日本語フォント(たとえば「IPAexゴシック」など)を設定しますが、Streamlit経由だと再設定が必要な場合があります。

import matplotlib.pyplot as plt
import matplotlib

# フォントを手動で指定
matplotlib.rcParams['font.family'] = 'IPAexGothic'  # または 'Noto Sans CJK JP'

インストール済みのフォントを確認したい場合:

import matplotlib.font_manager as fm
for font in fm.findSystemFonts(fontpaths=None, fontext='ttf'):
    if "ipag" in font.lower() or "noto" in font.lower():
        print(font)

✅ 4. Streamlit で日本語対応する際の補足(Streamlit特有の回避策)

Streamlit の st.pyplot(fig) は内部で fig.savefig() を呼ぶため、フォント設定が適用されないことがあります。以下のように、画像として一度保存し、それを読み込む方法が安定です:

import io
import streamlit as st
from PIL import Image

buf = io.BytesIO()
fig.savefig(buf, format="png", dpi=300, bbox_inches="tight")
buf.seek(0)
image = Image.open(buf)
st.image(image)

🎯 まとめ

方法 内容
bbox_inches="tight" 文字切れ・配置ズレを防ぐ
dpi=300 PowerPoint貼り付け用に高解像度
rcParams['font.family'] の明示設定 DejaVu Sans の代わりに日本語対応フォントを使う
BytesIO 保存経由で st.image() Streamlitでの日本語文字化けを完全回避

必要であれば、日本語フォントのインストール方法(たとえば IPAexGothicNoto Sans JP の追加)もご案内できます。

user:

最初、他の図で日本語が使えても、次にこの関数で出力すると、それ以降の図で日本語が使えなくなる現象が発生します。原因はわかりますか?

import japanize_matplotlib
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd

# フォントを手動で指定
matplotlib.rcParams["font.family"] = "IPAexGothic"  # または 'Noto Sans CJK JP'

import io

import streamlit as st
from PIL import Image


def plot_bar_with_ci(
    df: pd.DataFrame,
    target_col,
    title="Mean with Confidence Intervals",
    xlabel="Index",
    ylabel="Mean Value",
):
    """
    指定されたDataFrameからエラーバー付きの棒グラフを作成する。

    Args:
        df (pd.DataFrame): 'Index', 'mean', 'ci_lower', 'ci_upper' の列を含むDataFrame。

    Returns:
        matplotlib.figure.Figure: 描画された棒グラフのFigureオブジェクト。
    """
    # グラフスタイル設定(PowerPoint用にフォントサイズを大きめに)
    plt.rcParams.update(
        {
            "font.size": 14,
            "axes.labelsize": 16,
            "axes.titlesize": 18,
            "xtick.labelsize": 12,
            "ytick.labelsize": 12,
            "legend.fontsize": 12,
        }
    )
    plt.style.use("default")
    fig, ax = plt.subplots(figsize=(8, 6))

    # インデックスとバーの高さ、エラーバーの算出
    x = df.index.astype(str)
    y = df[target_col]
    yerr = [y - df["ci_lower"], df["ci_upper"] - y]

    # 色設定:正なら赤、負なら青
    colors = ["tomato" if val >= 0 else "steelblue" for val in y]

    # 棒グラフの描画
    bars = ax.bar(x, y, yerr=yerr, capsize=5, color=colors, edgecolor="black")

    # 軸やラベルの調整
    ax.set_xlabel(xlabel)
    ax.set_ylabel(ylabel)
    ax.set_title(title)
    ax.tick_params(axis="x", labelrotation=90)
    ax.tick_params(axis="y")
    ax.axhline(0, color="gray", linewidth=1, linestyle="--")

    # レイアウト調整(PowerPoint用)
    fig.tight_layout()

    buf = io.BytesIO()
    fig.savefig(buf, format="png", dpi=300, bbox_inches="tight")
    buf.seek(0)
    image = Image.open(buf)
    st.image(image)

    return fig

assistant:

この現象:

「最初は他の図で日本語が使えても、この関数で出力すると、それ以降の図で日本語が使えなくなる」

は、以下のような matplotlib のグローバル設定(rcParams)が途中で破壊されていることが主な原因です。


🔍 原因の本質

あなたの関数内で行っているこの処理:

plt.style.use("default")

japanize_matplotlib のフォント設定(rcParams['font.family'])を上書きして無効化しています。

  • japanize_matplotlibrcParams["font.family"] に日本語フォントを追加します。
  • しかし plt.style.use("default") を呼ぶと、これが DejaVu Sans に戻されます。
  • それにより以降の描画(他の図)でも日本語が表示されなくなります。

✅ 解決策

✅ 方法1:plt.style.use("default") を削除する(おすすめ)

# ❌ 削除してください
# plt.style.use("default")

これで rcParams が日本語フォントのまま維持されます。


✅ 方法2:plt.style.use("default") の後に再度フォントを指定し直す

どうしてもスタイルをリセットしたい場合は、次のようにフォント指定を後に移動します:

plt.style.use("default")
matplotlib.rcParams["font.family"] = "IPAexGothic"

これにより、スタイルはデフォルトに戻しつつ、日本語フォントだけは上書きできます。


🎯 まとめ

現象 原因 解決策
他の図で日本語が使えなくなる plt.style.use("default")rcParams を上書き 削除する or フォント再指定

✅ 改善済みコード抜粋(修正ポイント)

def plot_bar_with_ci(...):
    # グラフスタイル設定(PowerPoint用にフォントサイズを大きめに)
    plt.rcParams.update(
        {
            "font.size": 14,
            "axes.labelsize": 16,
            "axes.titlesize": 18,
            "xtick.labelsize": 12,
            "ytick.labelsize": 12,
            "legend.fontsize": 12,
            "font.family": "IPAexGothic",  # ← ここで明示
        }
    )
    
    # plt.style.use("default") ← これは削除する(または上に移動)

必要であれば、グローバル設定のリセットや復元のサンプルコードも提供できます。ご希望あればどうぞ。

よかったです!🎉
plt.style.use("default") の落とし穴は意外と多くの人がハマるポイントなので、解決できて安心しました。

もし今後、「複数の図でスタイルやフォントを切り替えながら描画したい」ようなケースがあれば、matplotlib.rc_context() を使った一時的なスタイル切替もおすすめですよ(設定の影響を局所化できます)。

何か他にも疑問や別の図の改善案などあれば、いつでもどうぞ!🖼📊✨

user:

次のような構成の pandas dataframe 形式ファイルがあります。

Variable mean ci_lower ci_upper
X1 1.5 1.0 2.0
X2 1.0 0.5 1.5
X3 -1.0 -2.0 -0.5

これを入力として、Variableを縦軸に、meanの値を横軸にした横向きの棒グラフを描画したfigを返り値とするPython関数を書いてください。

これをPowerPointにそのまま貼り付けても文字等が見えるようにしたいです。また、横軸のラベルは90度傾けてほしいです。ci_lowerとci_upperは信頼区間を表し、これはエラーバーとして描画してください(ci_lowerやci_upperの列がない場合は、信頼区間の値が計算されていないものとみなし、エラーバーは表示しないでください)。meanの値が正の値ならば赤色、負の値ならば青色にしてください。

assistant:

以下の関数は、ご指定の要件をすべて満たす 横向き(水平)棒グラフを描画するものです。PowerPoint貼付用に見やすく調整されており、信頼区間(ci_lower, ci_upper)が存在しない場合も柔軟に対応します。


✅ 横向き棒グラフを描画するPython関数

import matplotlib.pyplot as plt
import matplotlib
import pandas as pd

# 日本語フォントが必要な場合は有効にする(ここでは例として)
matplotlib.rcParams["font.family"] = "IPAexGothic"  # または Noto Sans CJK JP

def plot_horizontal_bar_with_ci(df: pd.DataFrame, title="Mean with Confidence Intervals"):
    """
    指定されたDataFrameからエラーバー付きの横向き棒グラフを作成する。

    Args:
        df (pd.DataFrame): 'Variable', 'mean' を含み、任意で 'ci_lower', 'ci_upper' 列を含むDataFrame。
        title (str): グラフタイトル。

    Returns:
        matplotlib.figure.Figure: 描画された棒グラフのFigureオブジェクト。
    """
    # スタイル設定
    plt.rcParams.update({
        "font.size": 14,
        "axes.labelsize": 16,
        "axes.titlesize": 18,
        "xtick.labelsize": 12,
        "ytick.labelsize": 12,
        "legend.fontsize": 12,
    })

    fig, ax = plt.subplots(figsize=(8, 6))

    # 軸情報
    y = df["Variable"]
    x = df["mean"]
    colors = ["tomato" if val >= 0 else "steelblue" for val in x]

    # エラーバーの算出(あれば)
    if {"ci_lower", "ci_upper"}.issubset(df.columns):
        xerr = [x - df["ci_lower"], df["ci_upper"] - x]
    else:
        xerr = None

    # 横棒グラフの描画
    bars = ax.barh(y, x, xerr=xerr, capsize=5, color=colors, edgecolor="black")

    # 軸設定
    ax.set_xlabel("Mean", fontsize=14)
    ax.set_ylabel("Variable", fontsize=14)
    ax.set_title(title, fontsize=16)
    ax.axvline(0, color="gray", linewidth=1, linestyle="--")
    ax.tick_params(axis="x", labelrotation=90)

    fig.tight_layout()
    return fig

📌 使用例

# サンプルデータ
data = {
    "Variable": ["X1", "X2", "X3"],
    "mean": [1.5, 1.0, -1.0],
    "ci_lower": [1.0, 0.5, -2.0],
    "ci_upper": [2.0, 1.5, -0.5],
}
df = pd.DataFrame(data)

# グラフ生成
fig = plot_horizontal_bar_with_ci(df)
plt.show()

🎯 補足

  • 信頼区間なしでも動作:
    ci_lower, ci_upper が列に含まれていなければ、xerr=None となりエラーバーは描画されません。

  • PowerPoint向け

    • dpi=300fig.savefig() すれば高解像度。
    • tight_layout() により文字が切れにくくなっています。
  • 日本語フォント
    必要に応じて IPAexGothicNoto Sans CJK JP を使ってください。


ご希望があれば、Streamlit対応・画像保存付きのバージョンも提供できます。

user:

たくさん描くと、こんなワーニングが出ますね。対処法を教えてください。

/Users/maskot/streamlit-app/causal/plot_bar_with_ci.py:43: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`). Consider using `matplotlib.pyplot.close()`.
  fig, ax = plt.subplots(figsize=(10, 6), dpi=300)

assistant:

この警告:

RuntimeWarning: More than 20 figures have been opened. ... Consider using matplotlib.pyplot.close().

は、開いた matplotlibFigure オブジェクトが閉じられずに溜まり続けているために出ているものです。これはメモリ使用量の増加や描画の遅延・クラッシュを引き起こす可能性があります。


✅ 原因

plt.subplots() などで作成した Figure は、明示的に plt.close(fig) で閉じない限り保持され続けるため、繰り返し作成しているとメモリを圧迫します。


✅ 対処法

✅ 方法1:グラフを保存 or Streamlitで表示した後に plt.close(fig) で閉じる

# グラフを作成
fig, ax = plt.subplots(...)

# グラフ処理(表示や保存など)
# ...

# 終わったら明示的に閉じる
plt.close(fig)

これは特に関数内で繰り返しグラフを作成する場合に重要です。


✅ 方法2:plt.figure().number を使って現在の図数を制限する(手動で)

以下のようにして現在のオープン図数を確認・制御することもできます:

import matplotlib.pyplot as plt

# 開いているFigureの数
print(f"Open figures: {len(plt.get_fignums())}")

✅ 修正版コード例(関数内で plt.close(fig)

def plot_horizontal_bar_with_ci(df: pd.DataFrame, title="Mean with Confidence Intervals"):
    # スタイル設定(省略)

    fig, ax = plt.subplots(figsize=(8, 6))

    # 描画処理(省略)

    fig.tight_layout()

    # 表示・保存などに fig を返す前提なら、呼び出し側で plt.close(fig) をするのが理想
    # ただし Streamlit などで即表示して返さない場合は、関数内で閉じる
    plt.close(fig)

    return fig

✅ Streamlitとの併用時の注意点

Streamlit で fig を表示するには:

import io
from PIL import Image
import streamlit as st

buf = io.BytesIO()
fig.savefig(buf, format="png", dpi=300, bbox_inches="tight")
buf.seek(0)
st.image(Image.open(buf))

# 安全にクローズ
plt.close(fig)

🔧 オプション(警告を出さない設定)

警告を非表示にするだけなら:

import matplotlib as mpl
mpl.rcParams['figure.max_open_warning'] = 100  # デフォルトは20

ですが、根本解決ではなく、できる限り plt.close() で対処してください。


✅ まとめ

方法 内容
plt.close(fig) を使う 最も確実で推奨される方法
✅ Streamlit等で描画後に plt.close(fig) メモリリーク防止
⚠️ rcParams['figure.max_open_warning'] を変更 警告を抑えるだけ。根本解決にはならない

必要なら「多数のグラフを安全に生成&一括保存するユーティリティ関数」も提供できます。お気軽にどうぞ。

user:

次の関数を改変したコードを書いてください。改変内容は次のとおりです。

・target_col の降順に水平棒グラフを描画するオプションをつける(デフォルトではこれをオンにする)。
・variable_col 行にある全ての変数名を表示したいが、行数が多すぎると表示されないことがある。これを改良して、行数に応じて図の高さを変えたりして、常に全ての変数名が表示されるようにする。

以上の機能が追加されるよう、下記の関数を改変したコードを書いてください。

import matplotlib
import matplotlib.pyplot as plt
import pandas as pd

# 日本語フォントが必要な場合は有効にする(ここでは例として)
matplotlib.rcParams["font.family"] = "IPAexGothic"  # または Noto Sans CJK JP


def plot_horizontal_bar_with_ci(
    df: pd.DataFrame,
    variable_col,
    target_col,
    title="Mean with Confidence Intervals",
    xlabel="Mean",
    ylabel="Variable",
):
    """
    指定されたDataFrameからエラーバー付きの横向き棒グラフを作成する。

    Args:
        df (pd.DataFrame): 'Variable', 'mean' を含み、任意で 'ci_lower', 'ci_upper' 列を含むDataFrame。
        title (str): グラフタイトル。

    Returns:
        matplotlib.figure.Figure: 描画された棒グラフのFigureオブジェクト。
    """
    # スタイル設定
    plt.rcParams.update(
        {
            "font.size": 14,
            "axes.labelsize": 16,
            "axes.titlesize": 18,
            "xtick.labelsize": 12,
            "ytick.labelsize": 12,
            "legend.fontsize": 12,
        }
    )

    fig, ax = plt.subplots(figsize=(8, 6))

    # 軸情報
    y = df[variable_col]
    x = df[target_col]
    colors = ["tomato" if val >= 0 else "steelblue" for val in x]

    # エラーバーの算出(あれば)
    if {"ci_lower", "ci_upper"}.issubset(df.columns):
        xerr = [x - df["ci_lower"], df["ci_upper"] - x]
    else:
        xerr = None

    # 横棒グラフの描画
    bars = ax.barh(y, x, xerr=xerr, capsize=5, color=colors, edgecolor="black")

    # 軸設定
    ax.set_xlabel(xlabel)
    ax.set_ylabel(ylabel)
    ax.set_title(title)
    ax.axvline(0, color="gray", linewidth=1, linestyle="--")
    ax.tick_params(axis="x", labelrotation=90)

    fig.tight_layout()
    return fig

assistant:

以下は、指定された改変を反映した plot_horizontal_bar_with_ci() 関数の改良版です。


✅ 改良内容

  1. sort_descending: bool = True オプションを追加し、target_col の降順で並べ替え(デフォルトでオン)。
  2. データフレームの行数に応じて figsize の高さを動的に調整し、すべてのラベルが見えるように対応

🆕 改変済みコード

import matplotlib
import matplotlib.pyplot as plt
import pandas as pd

# 日本語フォント(必要に応じて有効化)
matplotlib.rcParams["font.family"] = "IPAexGothic"  # または 'Noto Sans CJK JP'

def plot_horizontal_bar_with_ci(
    df: pd.DataFrame,
    variable_col: str,
    target_col: str,
    title: str = "Mean with Confidence Intervals",
    xlabel: str = "Mean",
    ylabel: str = "Variable",
    sort_descending: bool = True,
    base_height: float = 0.5,
    min_height: float = 4,
    max_height: float = 20,
):
    """
    指定されたDataFrameからエラーバー付きの横向き棒グラフを作成する。

    Args:
        df (pd.DataFrame): variable_col, target_col を含み、任意で 'ci_lower', 'ci_upper' を含む。
        variable_col (str): 変数名の列。
        target_col (str): 平均値の列(棒の長さになる)。
        title (str): グラフタイトル。
        xlabel (str): X軸ラベル。
        ylabel (str): Y軸ラベル。
        sort_descending (bool): target_col を降順にソートするか(デフォルト: True)。
        base_height (float): 行ごとの高さ(単位:インチ)。
        min_height (float): 図の最小高さ(インチ)。
        max_height (float): 図の最大高さ(インチ)。

    Returns:
        matplotlib.figure.Figure: 描画された棒グラフのFigureオブジェクト。
    """
    # データの並べ替え(target_colの降順)
    if sort_descending:
        df = df.sort_values(by=target_col, ascending=False).reset_index(drop=True)

    # 行数に応じて図の高さを調整
    n_rows = df.shape[0]
    height = min(max(n_rows * base_height, min_height), max_height)

    # フォント・スタイル設定
    plt.rcParams.update({
        "font.size": 14,
        "axes.labelsize": 16,
        "axes.titlesize": 18,
        "xtick.labelsize": 12,
        "ytick.labelsize": 12,
        "legend.fontsize": 12,
    })

    # グラフの描画
    fig, ax = plt.subplots(figsize=(8, height))

    y = df[variable_col]
    x = df[target_col]
    colors = ["tomato" if val >= 0 else "steelblue" for val in x]

    if {"ci_lower", "ci_upper"}.issubset(df.columns):
        xerr = [x - df["ci_lower"], df["ci_upper"] - x]
    else:
        xerr = None

    bars = ax.barh(y, x, xerr=xerr, capsize=5, color=colors, edgecolor="black")

    # 軸・タイトル設定
    ax.set_xlabel(xlabel)
    ax.set_ylabel(ylabel)
    ax.set_title(title)
    ax.axvline(0, color="gray", linewidth=1, linestyle="--")
    ax.tick_params(axis="x", labelrotation=90)

    fig.tight_layout()
    return fig

✅ 使用例(20行以上でもOK)

# ダミーデータ例
import numpy as np

df = pd.DataFrame({
    "Variable": [f"X{i}" for i in range(1, 31)],
    "mean": np.random.uniform(-2, 2, size=30),
    "ci_lower": np.random.uniform(-3, 0, size=30),
    "ci_upper": np.random.uniform(0, 3, size=30),
})

fig = plot_horizontal_bar_with_ci(df, variable_col="Variable", target_col="mean")
plt.show()

🔧 補足オプション

  • base_height: 1行あたりの図の高さを調整(縦詰まりの回避に役立ちます)。
  • min_height, max_height: 最小・最大の高さ制限。

必要であれば、Streamlit対応版や画像ファイル保存版も拡張できますのでお申し付けください!

user:

ありがとうございました。ここまでの内容をブログにまとめたいので、タイトル案をいくつか提案してください。

assistant:

どういたしまして!以下に、今回の内容をカバーするブログ記事のタイトル案を複数ご提案します。用途や読者層(初心者〜中級者)に応じてお選びください。


🎯 テーマを押さえた王道系

  1. 「matplotlibで全変数を見せる横棒グラフ:ラベル欠けゼロへの工夫」
  2. 「Pythonで信頼区間付き横棒グラフを作る:変数ラベルが途切れない図を自動調整」
  3. 「PowerPoint貼付けOK!matplotlibで見やすい横向き棒グラフを作る方法」
  4. 「Python × matplotlibで横棒グラフ作成:ソートとラベル表示の完全ガイド」

📈 実用性・ビジネス分析寄り

  1. 「変数重要度を視覚化する横棒グラフ:matplotlibでソート&信頼区間も対応」
  2. 「CIつき横棒グラフをmatplotlibで描く:指標の比較や可視化に最適」
  3. 「matplotlibで“抜けのない可視化”を実現する:信頼区間+ラベル調整術」

🧰 技術・Tips寄り

  1. 「matplotlibで20行以上の横棒グラフを描くとラベルが消える問題を解決する」
  2. 「matplotlibのfigsizeをデータ量で自動調整する方法」
  3. 「グラフが多すぎて警告?plt.close()の意味と正しい使い方」

💡 軽め&読まれやすいトーン

  1. 「matplotlibで横棒グラフをキレイに描くには?変数名も全部見せたい!」
  2. 「Pythonで可視化:ラベルが切れない棒グラフを作るには」
  3. 「PowerPointに貼っても見やすい横棒グラフをPythonでつくる方法」

ご希望があれば、「Streamlitで使えるように」や「データサイエンスの業務活用」など、文脈に合わせたサブタイトルや導入文案もご提案できます。お気軽にどうぞ!

user:

plt.style や plt.close などの議論にフォーカスしたほうがよさそうな気がします

assistant:

なるほど、素晴らしい視点です!今回は単なる棒グラフ描画にとどまらず、

  • plt.style.use() によるフォント設定の破壊とその回避法
  • plt.close() を使わないことで起こるメモリリーク警告とその防止
  • それらが 複数図の連続出力やStreamlitアプリ に与える影響

など、matplotlib運用の落とし穴とベストプラクティスが主題になりますね。


🔥 それを踏まえたタイトル案(テーマ:matplotlibの落とし穴と実用対策)

🎯 テクニカル寄り・問題解決を強調

  1. 「matplotlibの落とし穴:plt.styleとplt.closeが壊す可視化の品質」
  2. 「グラフの見えないバグ:matplotlibで日本語が消える本当の理由」
  3. 「matplotlibで複数グラフを扱うときの注意点:styleとcloseの正しい使い方」
  4. 「figが増えすぎて警告?matplotlibで安全にグラフを量産する方法」
  5. 「matplotlibで日本語が突然消える?plt.styleが壊すフォント設定の真実」

🧰 実用性&アプリ開発文脈を意識

  1. 「Streamlitでグラフが壊れる?matplotlibのstyleとcloseの落とし穴」
  2. 「matplotlibで図を繰り返し出力するなら、plt.close()は必須です」
  3. 「Python × matplotlib 実用Tips:plt.styleとplt.closeを正しく使う」
  4. 「PowerPointにも強い!matplotlibで大量の図を安全に描画する方法」

💡 やや読み物っぽい柔らかめタイトル

  1. 「どうして急に日本語が表示されない?matplotlibでハマった落とし穴」
  2. 「matplotlibで図を20個以上出したら怒られた話」
  3. 「グラフが増えたらバグった…matplotlibの正しい描き方、知ってますか?」

ご希望があれば、これらタイトルに合わせた導入文や構成案(章立て)も提案できます!

user:

「Python × matplotlib 実用Tips:plt.styleとplt.closeを正しく使う」でいきたいと思います。タイトルに沿って、詳しいまとめを書いてください。

assistant:

承知しました!以下に、ブログ記事「Python × matplotlib 実用Tips:plt.styleとplt.closeを正しく使う」の本文(詳しいまとめ)を構成付きでご提案します。


Python × matplotlib 実用Tips:plt.styleとplt.closeを正しく使う

はじめに:なぜ今、matplotlibの使い方を見直すのか?

Pythonで可視化といえば、やはり定番はmatplotlib
手軽にグラフを描画できる一方で、「たくさんの図を描く」「日本語フォントを設定する」「アプリに組み込む」といった実践的な場面になると、意外な落とし穴に直面します。

本記事では、特に重要な2点に絞って、実用的なTipsをご紹介します。

  • plt.style.use() によるフォント設定破壊問題
  • plt.close() を使わないことで起きるリソース警告とメモリ問題

これらの問題と対処法を、PowerPointに貼れる高解像度グラフStreamlitなどアプリ文脈でも役立つ形でまとめます。


1. plt.style.use() の意外な落とし穴:フォント設定が無効になる?

📌 問題の背景

import matplotlib.pyplot as plt
plt.style.use("ggplot")
matplotlib.rcParams["font.family"] = "IPAexGothic"

上記のようにスタイルとフォント設定を併用した場合、plt.style.use()の後にフォント設定を書いても反映されないことがあります。

⚠ なぜ起きる?

plt.style.use() は内部的に rcParams を一気に上書きしてしまうため、それ以降に行った rcParams の変更が適用されない場合があるのです。特に font.family は影響を受けやすく、日本語フォントが表示されなくなる原因になります。

✅ 対処法:スタイル設定の後にフォント設定を上書きする

plt.style.use("ggplot")  # 先にスタイルを指定
matplotlib.rcParams["font.family"] = "IPAexGothic"  # 後からフォントを上書き

この順番を守れば、スタイルとフォント設定を両立できます。


2. plt.close() を忘れると、図が増えすぎて警告が出る

📌 複数の図を描いたときに出る警告

RuntimeWarning: More than 20 figures have been opened.
Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed.

この警告は、一度描いた図(Figureオブジェクト)がメモリ上に溜まり続けているために発生します。特にループ内で大量の図を描く処理をしている場合、アプリやバッチ処理がメモリを圧迫して落ちることもあります。

✅ 対処法:使い終わった図は plt.close(fig) で明示的に閉じる

fig = plot_horizontal_bar_with_ci(df, ...)
# 保存や表示などを終えた後に明示的に閉じる
plt.close(fig)

これにより、リソースリークを防ぎ、描画パフォーマンスも安定します。特にStreamlitのようなWebアプリでは、図を開きっぱなしにしておくとセッションが不安定になることがあります。


3. 応用例:多変数の感度分析グラフを安全に描く関数

🎯 目的

  • PowerPointに貼れるよう高解像度
  • 日本語変数名に対応
  • meanと信頼区間(ci_lower, ci_upper)付きの水平棒グラフ
  • 変数数が多くても全て見切れないように高さを自動調整
  • meanが正なら赤、負なら青で色分け

✅ 実装済の関数(抜粋)

def plot_horizontal_bar_with_ci(..., sort_by_target_desc=True):
    # デフォルトで降順ソート
    if sort_by_target_desc:
        df = df.sort_values(by=target_col, ascending=False)

    # 自動高さ調整(1行あたり0.4インチ、最小6インチ)
    height_per_var = 0.4
    fig_height = max(6, len(df) * height_per_var)

    fig, ax = plt.subplots(figsize=(8, fig_height), dpi=300)
    ...
    return fig

このように、表示品質・処理の安定性・柔軟性を兼ね備えたグラフ関数を作っておけば、分析結果をPowerPointやStreamlitにそのまま貼れる形で出力できます。


おわりに:スタイルもメモリも制御できてこそ、matplotlib上級者

matplotlibは強力なライブラリですが、細かな設定を知らないとグラフが壊れたり、警告が出たりしてしまいます。今回ご紹介した以下のTipsを押さえておけば、高品質で安定したグラフ描画が可能になります。

  • plt.style.use()は便利だが、rcParamsが上書きされる点に注意
  • フォント設定はstyleの後に明示的に行うこと
  • plt.close(fig)で図をこまめに閉じ、メモリリークを防ぐこと
  • 変数数に応じてfigsizeを動的に変えることで、文字切れを回避すること

これらを意識すれば、あなたのPython可視化環境は一段上のレベルに進化するはずです。


ご希望があれば、記事用のコードブロック・図・Streamlit応用なども追記できます!

user:

ありがとうございました!

assistant:

どういたしまして!こちらこそ、いつも丁寧に進めてくださりありがとうございます 🙌
記事の完成、楽しみにしています。タイトルも内容も実用的で、多くの人に役立つものになるはずです!

また何かあればいつでもどうぞ。素敵な可視化ライフを!📊✨

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?