閉じる

Pythonで折れ線・棒・散布図を作る方法 MatplotlibとSeaborn

データをグラフで可視化できると、数字の「傾向」や「違い」が直感的に分かります。

本記事では、Python初心者の方でもすぐに使えるように、MatplotlibとSeabornで折れ線・棒・散布図を作る基本を、日本語表示に強い設定(日本語フォントとマイナス記号)を含めて丁寧に解説します。

Python初心者向けの準備と環境

必要なライブラリのインストール

可視化にはMatplotlibとSeabornを使います。

データ整形にはpandas、数値生成にNumPy、日本語の文字化け防止にjapanize_matplotlibを使います。

Jupyterを利用する場合はJupyterLabも入れておくと便利です。

Shell
# 仮想環境の利用を推奨します(例: venvやconda)
# 必要ライブラリのインストール
pip install matplotlib seaborn pandas numpy japanize-matplotlib jupyterlab
実行結果
# 出力例(一部)
# Successfully installed matplotlib-3.x seaborn-0.12.x pandas-2.x numpy-1.x japanize-matplotlib-1.1.3 ...

バージョンの確認

ライブラリのバージョンが古いと動作が異なることがあります。

確認しておくと安心です。

Python
import matplotlib
import seaborn as sns
import pandas as pd
import numpy as np

print("matplotlib:", matplotlib.__version__)
print("seaborn   :", sns.__version__)
print("pandas    :", pd.__version__)
print("numpy     :", np.__version__)
実行結果
matplotlib: 3.10.6
seaborn   : 0.13.2
pandas    : 2.3.2
numpy     : 2.3.3

日本語の文字化け対策

Matplotlibは標準設定だと日本語が文字化けします。

japanize_matplotlibを読み込むだけで、日本語対応のフォントとマイナス記号の設定が自動で適用されます。

以降のサンプルでは毎回読み込みます。

Python
# 日本語表示テスト用の最小コード
import matplotlib.pyplot as plt
import japanize_matplotlib  # これだけで日本語対応フォントが有効化されます

# マイナス記号が豆腐(□)にならないようにするための保険
import matplotlib as mpl
mpl.rcParams["axes.unicode_minus"] = False

plt.figure(figsize=(4, 3))
plt.title("日本語のタイトル")
plt.xlabel("横軸(サンプル)")
plt.ylabel("縦軸(サンプル)")
plt.plot([-2, -1, 0, 1, 2], [1, 2, 0, 2, 1], marker="o")
plt.tight_layout()
plt.show()

print("日本語とマイナス記号の表示テストが完了しました。")
実行結果
日本語とマイナス記号の表示テストが完了しました。
注意

環境によっては初回実行時にフォントキャッシュが作られます

数秒かかることがあります。

基本のインポートと表示の流れ

グラフの基本は「データを用意 → 図形を描く → 体裁(タイトル等)を整える → 表示または保存」です。

最小の流れを確認します。

Python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import japanize_matplotlib  # 日本語対応
import matplotlib as mpl
mpl.rcParams["axes.unicode_minus"] = False  # マイナス記号対策

# Seabornのテーマ(後で上書き可能)
# フォントの再設定が必要になるので注意(日本語が文字化けします)
sns.set_theme(style="whitegrid")
mpl.rcParams['font.family'] = 'IPAexGothic'  # 日本語対応フォント

# サンプルデータ
x = np.arange(6)  # 0~5
y = np.array([5, 3, 4, 7, 6, 8])

plt.figure(figsize=(5, 3))
plt.plot(x, y, marker="o", label="サンプル系列")
plt.title("最小構成の折れ線グラフ")
plt.xlabel("X")
plt.ylabel("Y")
plt.legend()
plt.tight_layout()
plt.show()

print("基本の表示フローを確認しました。")
実行結果
基本の表示フローを確認しました。

サンプルデータの用意

以降の解説で使い回せるように、月別の売上データと散布図用の疑似データを用意します。

Python
import numpy as np
import pandas as pd

# 月(1~6月)
months = np.arange(1, 
7)

# 店舗A/Bの売上(例)
sales_A = np.array([50, 65, 80, 60, 75, 90])
sales_B = np.array([40, 55, 60, 70, 65, 85])

# 地域カテゴリ(散布図の色分けに使う)
regions = np.array(["東", "西", "南", "北", "東", "西"])

# 月ごとに軽いノイズを入れた座標(散布図)
rng = np.random.default_rng(42)
x_scatter = months + rng.normal(0, 0.15, size=months.size)
y_scatter = sales_A * 0.8 + rng.normal(0, 5, size=months.size)

# DataFrameにまとめ
df = pd.DataFrame({
    "month": months,
    "sales_A": sales_A,
    "sales_B": sales_B,
    "region": regions,
    "x_scatter": x_scatter,
    "y_scatter": y_scatter
})

# Seaborn向けに縦長形式へ(折れ線や棒の色分けに便利)
df_long = df.melt(id_vars=["month", "region"],
                  value_vars=["sales_A", "sales_B"],
                  var_name="store",
                  value_name="sales")

print(df.head(3))
print(df_long.head(3))
実行結果
   month  sales_A  sales_B region  x_scatter   y_scatter
0      1       50       40      東   1.045556  39.653835
1      2       65       55      西   2.074435  46.310879
2      3       80       60      南   2.873789  64.938111
   month region    store  sales
0      1      東  sales_A     50
1      2      西  sales_A     65
2      3      南  sales_A     80

ポイント: Seabornはdf_longのような「縦長」(tidy)データと相性が良いです。

Matplotlibで折れ線・棒グラフ・散布図

折れ線グラフ(plot)の基本

2系列の折れ線と凡例

Python
import matplotlib.pyplot as plt
import japanize_matplotlib
import matplotlib as mpl
import numpy as np

# 月(1~6月)
months = np.arange(1, 
7)

# 店舗A/Bの売上(例)
sales_A = np.array([50, 65, 80, 60, 75, 90])
sales_B = np.array([40, 55, 60, 70, 65, 85])

mpl.rcParams["axes.unicode_minus"] = False


# 前セクションで作成した months, sales_A, sales_B を利用
plt.figure(figsize=(6, 4))
plt.plot(months, sales_A, marker="o", color="C0", label="A店")
plt.plot(months, sales_B, marker="s", color="C1", label="B店")
plt.title("月別売上の推移")
plt.xlabel("月")
plt.ylabel("売上(万円)")
plt.xticks(months)
plt.legend(title="店舗")
plt.grid(True, linestyle="--", alpha=0.4)
plt.tight_layout()
plt.show()

print("折れ線グラフを描画しました。")
実行結果
折れ線グラフを描画しました。

棒グラフ(bar)の基本

月別・店舗別のグループ化棒グラフ

Python
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
import matplotlib as mpl

# 月(1~6月)
months = np.arange(1, 
7)

# 店舗A/Bの売上(例)
sales_A = np.array([50, 65, 80, 60, 75, 90])
sales_B = np.array([40, 55, 60, 70, 65, 85])


mpl.rcParams["axes.unicode_minus"] = False

index = np.arange(len(months))  # x位置
width = 0.35                    # 棒の幅

plt.figure(figsize=(7, 4))
plt.bar(index - width/2, sales_A, width=width, color="C0", label="A店")
plt.bar(index + width/2, sales_B, width=width, color="C1", label="B店")

# 軸とタイトル
plt.title("月別売上(棒グラフ)")
plt.xlabel("月")
plt.ylabel("売上(万円)")
plt.xticks(index, months)

# 棒の上に値を注記
for i, v in enumerate(sales_A):
    plt.text(i - width/2, v + 1, f"{v}", ha="center", va="bottom", fontsize=9)
for i, v in enumerate(sales_B):
    plt.text(i + width/2, v + 1, f"{v}", ha="center", va="bottom", fontsize=9)

plt.legend(title="店舗")
plt.tight_layout()
plt.show()

print("棒グラフを描画しました。")
実行結果
棒グラフを描画しました。

散布図(scatter)の基本

カテゴリで色分けし、透過で重なりを見やすくする

Python
import matplotlib.pyplot as plt
import japanize_matplotlib
import matplotlib as mpl
import numpy as np
import pandas as pd

mpl.rcParams["axes.unicode_minus"] = False

# 月(1~6月)
months = np.arange(1, 7)

# 店舗A/Bの売上(例)
sales_A = np.array([50, 65, 80, 60, 75, 90])
sales_B = np.array([40, 55, 60, 70, 65, 85])

# 地域カテゴリ(散布図の色分けに使う)
regions = np.array(["東", "西", "南", "北", "東", "西"])

# 月ごとに軽いノイズを入れた座標(散布図)
rng = np.random.default_rng(42)
x_scatter = months + rng.normal(0, 0.15, size=months.size)
y_scatter = sales_A * 0.8 + rng.normal(0, 5, size=months.size)

# DataFrameにまとめ
df = pd.DataFrame({
    "month": months,
    "sales_A": sales_A,
    "sales_B": sales_B,
    "region": regions,
    "x_scatter": x_scatter,
    "y_scatter": y_scatter
})

# regionごとに色を割り当て
region_to_color = {"東": "C0", "西": "C1", "南": "C2", "北": "C3"}

plt.figure(figsize=(6, 4))
for r in sorted(set(regions)):
    mask = (df["region"] == r)
    plt.scatter(df.loc[mask, "x_scatter"],
                df.loc[mask, "y_scatter"],
                s=60, alpha=0.8, label=f"地域:{r}",
                color=region_to_color.get(r, "C7"),
                edgecolor="white", linewidth=0.7)

plt.title("散布図の基本例")
plt.xlabel("説明変数X")
plt.ylabel("目的変数Y")
plt.grid(True, linestyle=":", alpha=0.5)
plt.legend()
plt.tight_layout()
plt.show()

print("散布図を描画しました。")
実行結果
散布図を描画しました。

タイトル・軸ラベル・凡例の設定

読みやすいグラフは「何を示すか」が一目で分かります

タイトル、軸ラベル、凡例を適切に設定しましょう。

Python
import matplotlib.pyplot as plt
import japanize_matplotlib
import matplotlib as mpl
mpl.rcParams["axes.unicode_minus"] = False

plt.figure(figsize=(6, 4))
plt.plot(months, sales_A, marker="o", color="C0", label="A店")
plt.title("月別売上の推移(見出しを明確に)")
plt.xlabel("月(月初基準)")
plt.ylabel("売上(万円, 税抜)")
plt.legend(title="店舗", loc="upper left", bbox_to_anchor=(1.02, 1.0))  # グラフ外に凡例
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

print("タイトル・軸ラベル・凡例の設定例を描画しました。")
実行結果
タイトル・軸ラベル・凡例の設定例を描画しました。

グリッド・色・マーカーの指定

好みや用途に応じて線種や点の形状を変えると、複数系列も区別しやすくなります。

Python
import matplotlib.pyplot as plt
import japanize_matplotlib
import matplotlib as mpl
import numpy as np
mpl.rcParams["axes.unicode_minus"] = False

# 月(1~6月)
months = np.arange(1, 7)

# 店舗A/Bの売上(例)
sales_A = np.array([50, 65, 80, 60, 75, 90])
sales_B = np.array([40, 55, 60, 70, 65, 85])

plt.figure(figsize=(6, 4))
plt.plot(months, sales_A, marker="o", color="C0", label="A店")
plt.title("月別売上の推移(見出しを明確に)")
plt.xlabel("月(月初基準)")
plt.ylabel("売上(万円, 税抜)")
plt.legend(title="店舗", loc="upper left", bbox_to_anchor=(1.02, 1.0))  # グラフ外に凡例
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

print("タイトル・軸ラベル・凡例の設定例を描画しました。")
実行結果
色・線種・マーカーを指定した例を描画しました。

よく使う主な指定(抜粋)

下表はMatplotlibの折れ線や散布図でよく使う引数の要約です。

種別引数説明
color“C0”, “#1f77b4”既定の色循環やHEX指定
線種linestyle“-“, “–“, “:”実線や破線
マーカーmarker“o”, “s”, “^”点の形状
透過alpha0.3〜1.0重なりを見やすく
サイズmarkersize, s6, 60折れ線はmarkersize、散布はs

画像として保存

レポート提出や共有には画像保存が必須です。

plt.savefigで高解像度PNG等に書き出します。

Python
import os
import matplotlib.pyplot as plt
import japanize_matplotlib
import matplotlib as mpl
import numpy as np
mpl.rcParams["axes.unicode_minus"] = False

# 月(1~6月)
months = np.arange(1, 7)

# 店舗A/Bの売上(例)
sales_A = np.array([50, 65, 80, 60, 75, 90])
sales_B = np.array([40, 55, 60, 70, 65, 85])

plt.figure(figsize=(6, 4))
plt.plot(months, sales_A, marker="o", label="A店")
plt.title("保存用のグラフ")
plt.xlabel("月")
plt.ylabel("売上(万円)")
plt.legend()
plt.tight_layout()

out_path = "sales_line.png"
plt.savefig(out_path, dpi=150, bbox_inches="tight")  # dpiで解像度指定
plt.close()

print("保存しました:", os.path.abspath(out_path))
実行結果
保存しました: /your/project/path/sales_line.png

Seabornで見やすく可視化

SeabornはMatplotlibの上に構築された高水準ライブラリで、少ないコードで統計的に見やすい図を描けます。

DataFrameを直接渡すだけで、カテゴリで色分けや集計を簡単に行えます。

テーマ(style)と色の設定

Python
import seaborn as sns
import japanize_matplotlib
import matplotlib as mpl
mpl.rcParams["axes.unicode_minus"] = False

# テーマ設定
sns.set_theme(style="whitegrid", context="notebook")  # contextでフォントサイズ等を一括調整

# カラーパレットの確認・変更
palette = sns.color_palette("Set2", n_colors=8)
print("使用パレット:", palette.as_hex())
実行結果
使用パレット: ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f', '#e5c494', '#b3b3b3']

折れ線(lineplot)の描き方

Python
import seaborn as sns
import matplotlib.pyplot as plt
import japanize_matplotlib
import matplotlib as mpl
import numpy as np
import pandas as pd
mpl.rcParams["axes.unicode_minus"] = False

# 月(1~6月)
months = np.arange(1, 7)

# 店舗A/Bの売上(例)
sales_A = np.array([50, 65, 80, 60, 75, 90])
sales_B = np.array([40, 55, 60, 70, 65, 85])

# 地域カテゴリ(散布図の色分けに使う)
regions = np.array(["東", "西", "南", "北", "東", "西"])

# 月ごとに軽いノイズを入れた座標(散布図)
rng = np.random.default_rng(42)
x_scatter = months + rng.normal(0, 0.15, size=months.size)
y_scatter = sales_A * 0.8 + rng.normal(0, 5, size=months.size)

# DataFrameにまとめ
df = pd.DataFrame({
    "month": months,
    "sales_A": sales_A,
    "sales_B": sales_B,
    "region": regions,
    "x_scatter": x_scatter,
    "y_scatter": y_scatter
})

# Seaborn向けに縦長形式へ(折れ線や棒の色分けに便利)
df_long = df.melt(id_vars=["month", "region"],
                  value_vars=["sales_A", "sales_B"],
                  var_name="store",
                  value_name="sales")

plt.figure(figsize=(6, 4))
sns.lineplot(data=df_long, x="month", y="sales", hue="store", marker="o")
plt.title("Seabornの折れ線(lineplot)")
plt.xlabel("月")
plt.ylabel("売上(万円)")
plt.tight_layout()
plt.show()

print("Seabornのlineplotを描画しました。")
実行結果
Seabornのlineplotを描画しました。

棒グラフ(barplot)の描き方

平均や合計など集計の可視化に便利です。

Seaborn 0.12以降はerrorbar引数で誤差表示を制御します。

Python
import seaborn as sns
import matplotlib.pyplot as plt
import japanize_matplotlib
import matplotlib as mpl
import numpy as np
import pandas as pd
mpl.rcParams["axes.unicode_minus"] = False

# 月(1~6月)
months = np.arange(1, 7)

# 店舗A/Bの売上(例)
sales_A = np.array([50, 65, 80, 60, 75, 90])
sales_B = np.array([40, 55, 60, 70, 65, 85])

# 地域カテゴリ(散布図の色分けに使う)
regions = np.array(["東", "西", "南", "北", "東", "西"])

# 月ごとに軽いノイズを入れた座標(散布図)
rng = np.random.default_rng(42)
x_scatter = months + rng.normal(0, 0.15, size=months.size)
y_scatter = sales_A * 0.8 + rng.normal(0, 5, size=months.size)

# DataFrameにまとめ
df = pd.DataFrame({
    "month": months,
    "sales_A": sales_A,
    "sales_B": sales_B,
    "region": regions,
    "x_scatter": x_scatter,
    "y_scatter": y_scatter
})

# Seaborn向けに縦長形式へ(折れ線や棒の色分けに便利)
df_long = df.melt(id_vars=["month", "region"],
                  value_vars=["sales_A", "sales_B"],
                  var_name="store",
                  value_name="sales")

plt.figure(figsize=(7, 4))
# 店舗×月の売上をそのまま棒で(誤差線なし)
sns.barplot(data=df_long, x="month", y="sales", hue="store", errorbar=None, palette="Set2")
plt.title("Seabornの棒グラフ(barplot)")
plt.xlabel("月")
plt.ylabel("売上(万円)")
plt.tight_layout()
plt.show()

print("Seabornのbarplotを描画しました。")
実行結果
Seabornのbarplotを描画しました。

散布図(scatterplot)の描き方

Seabornではhuesizeで、カテゴリや量的変数を直感的に表現できます。

Python
import seaborn as sns
import matplotlib.pyplot as plt
import japanize_matplotlib
import matplotlib as mpl
mpl.rcParams["axes.unicode_minus"] = False

plt.figure(figsize=(6, 4))
sns.scatterplot(data=df, x="x_scatter", y="y_scatter",
                hue="region", palette="tab10", s=70, alpha=0.85, edgecolor="white", linewidth=0.7)
plt.title("Seabornの散布図(scatterplot)")
plt.xlabel("説明変数X")
plt.ylabel("目的変数Y")
plt.tight_layout()
plt.show()

print("Seabornのscatterplotを描画しました。")
実行結果
Seabornのscatterplotを描画しました。

DataFrameとの相性と簡単な使い方

Seabornは列名をそのままxyhueに渡すだけで動きます。

以下は月別合計売上を作って棒グラフにする例です。

Python
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import japanize_matplotlib
import matplotlib as mpl
mpl.rcParams["axes.unicode_minus"] = False

# 月ごとの総売上(万円)
df_total = df.assign(total=lambda d: d["sales_A"] + d["sales_B"])[["month", "total"]]

plt.figure(figsize=(5, 3.5))
sns.barplot(data=df_total, x="month", y="total", color="C0")  # hue無しなら単色棒
plt.title("月別総売上(Seaborn + DataFrame)")
plt.xlabel("月")
plt.ylabel("総売上(万円)")
plt.tight_layout()
plt.show()

print("DataFrameとSeabornの連携例を描画しました。")
実行結果
DataFrameとSeabornの連携例を描画しました。

よくあるつまずきと対処法

日本語フォントが出ない時のチェック

日本語が□(豆腐)になる場合、次の順に確認します。

記事のコードでは常にimport japanize_matplotlibを入れています。

  • コードの先頭でimport japanize_matplotlibを実行しているか
  • 一度キャッシュを削除する(パスはmatplotlib.get_cachedir()で確認)
  • mpl.rcParams["font.family"]の中身を確認し、IPAex系が有効かをチェック
  • Seabornのset_themeを使用した場合、その後に日本語対応フォントを再設定しているか
Python
import matplotlib as mpl
import matplotlib
print("font.family:", mpl.rcParams.get("font.family"))
print("cache_dir  :", matplotlib.get_cachedir())
mpl.rcParams['font.family'] = 'IPAexGothic'  # 日本語対応フォント
print("font.family:", mpl.rcParams.get("font.family"))
実行結果
font.family: ['sans-serif']
cache_dir  : C:\Users\User\.matplotlib
font.family: ['IPAexGothic']

文字化けとマイナス記号の表示対策

マイナス記号は特に文字化けしやすいため、保険として以下を毎回設定します。

Python
import matplotlib as mpl
mpl.rcParams["axes.unicode_minus"] = False
print("axes.unicode_minus:", mpl.rcParams["axes.unicode_minus"])
実行結果
axes.unicode_minus: False

Notebookでグラフが表示されない時

Jupyter環境ではplt.show()が無くても表示されることがありますが、表示されない場合は必ずplt.show()を明示しましょう。

古いNotebook設定なら、先頭セルで%matplotlib inlineを使うと安定します。

Python
# Jupyterの先頭セルで
# %matplotlib inline
print("Notebookで表示が不安定な場合は、%matplotlib inline と plt.show() を併用します。")
実行結果
Notebookで表示が不安定な場合は、%matplotlib inline と plt.show() を併用します。

点が重なる時のコツ

散布図で点が重なって見えないときは、以下の工夫が有効です。

どれか一つでも効果はあります

  • 透過度alphaを下げる(例: 0.3〜0.6)
  • 点のサイズsを小さくする・境界線を付ける
  • 微小な乱数でジッターを与える
  • Seabornのhuestyleで系列を分ける
Python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
import matplotlib as mpl
mpl.rcParams["axes.unicode_minus"] = False

# サンプルデータを作成
np.random.seed(0)
df = pd.DataFrame({
    "x_scatter": np.random.randint(1, 5, size=100),  # 離散的なカテゴリっぽいX
    "y_scatter": np.random.normal(10, 3, size=100)   # 正規分布に従うY
})

# xに微小ノイズを入れて重なりを回避(ジッター)
x_jitter = df["x_scatter"] + np.random.normal(0, 0.05, size=len(df))

plt.figure(figsize=(6, 4))
plt.scatter(x_jitter, df["y_scatter"], s=40, alpha=0.5, edgecolor="white", linewidth=0.6)
plt.title("点の重なりを避ける(ジッター+透過)")
plt.xlabel("X(ジッターあり)")
plt.ylabel("Y")
plt.tight_layout()
plt.show()

print("重なり対策としてジッターと透過を適用しました。")
実行結果
重なり対策としてジッターと透過を適用しました。

MatplotlibとSeabornの使い分けの目安

どちらも重要ですが、目的で使い分けると効率的です。

  • カスタマイズ性重視や細かな描画制御: Matplotlib
  • 少ないコードで整った図、統計的可視化やDataFrame直渡し: Seaborn

以下に簡単な比較を示します。

観点MatplotlibSeaborn
学習コスト低〜中
コード量やや多い少なめ
デフォルトの見た目素朴整っている
細かい制御非常に得意可能だがMatplotlib併用が前提
DataFrameとの相性普通とても良い
統計的機能(平均・信頼区間)自前実装標準でサポート

実務ではSeabornで素早く概観→必要になったらMatplotlibで細部を追い込む、という流れが多いです。

まとめ

本記事では、Python初心者の方がすぐに使えるように、MatplotlibとSeabornで折れ線・棒・散布図を描く基本を、日本語表示の対策plt.savefigによる画像保存まで含めて解説しました。

japanize_matplotlibの読み込みとaxes.unicode_minus=Falseの設定を習慣化すれば、文字化けとマイナス記号の問題はほぼ回避できます。

SeabornはDataFrameをそのまま渡すだけで整った図が出せるため、探索的分析に最適です。

一方で、細かな調整や高度なカスタマイズにはMatplotlibが強力です。

まずはサンプルを写経し、「データ → 図形 → 装飾 → 保存」の流れを体に覚えさせるところから始めてみてください。

可視化が自在にできるようになると、データ理解と意思決定のスピードが一段と上がります。

この記事を書いた人
エーテリア編集部
エーテリア編集部

人気のPythonを初めて学ぶ方向けに、文法の基本から小さな自動化まで、実際に手を動かして理解できる記事を書いています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!