Rotate xtick labels and fine-adjust position in matplotlib, seaborn and plotnine.
python: 3.12.11
pandas: 2.3.3
matplotlib: 3.10.0
seaborn: 0.13.2
plotnine: 0.15.3
動機
matplotlib (やそれをバックエンドに利用しているseabornやplotnine) で、X軸目盛ラベル(xtick labels)をシンプルに回転させて、頭ないし尻が目盛位置に来るように設定すると、±90度以外では目盛り線の位置から微妙にズレてしまい、格好悪い。
これを強引に解決する方法を記載する。
(もっと良い方法をご存知の方おりましたら、コメントお願いします!)
summary
x軸目盛ラベルの末尾に改行を加えてmatplotlibのlinespacing変数が機能するようにし、
linespacingの値で強引に左右を調整する。
その上で、x軸目盛ラベルやx軸タイトルの上下位置を調整する。
(上下位置については、調整のための引数が機能するので簡単に達成できる)
モジュール読み込みおよびサンプルデータ用意
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import plotnine as p9
d = pd.DataFrame({"variable": [chr(i + 65) * 10 for i in range(8)],
"value": range(1, 9)})
d.head(2)
matplotlib (および前振り)
言わずもがなではあるが、何もしないと以下のようにラベルが重なってしまう
# xラベルにしか用がないのでグラフ部分を極小化している。例示都合なので、実際に利用する際は要修正。
fig, ax = plt.subplots(figsize=(7, 0.1))
# base
ax.bar(d["variable"], d["value"])
ax.set_xlabel("variable")
ax.set_ylabel("value")
plt.show()
素朴に45度回転させる (基準位置は右端)
fig, ax = plt.subplots(figsize=(7, 0.1))
# base
ax.bar(d["variable"], d["value"])
ax.set_xlabel("variable")
ax.set_ylabel("value")
# xlabelを45度回転する (基準位置は右端)
ax.set_xticks(ax.get_xticks(), ax.get_xticklabels(), rotation=45, ha="right")
plt.show()
軸の目盛り線とラベルの左右位置が少しずれており、格好悪い
45度回転させ、強引にラベルの位置を調整する
fig, ax = plt.subplots(figsize=(7, 0.1))
# base
ax.bar(d["variable"] , d["value"])
ax.set_xlabel("variable")
ax.set_ylabel("value")
# 45度回転させ、強引にラベルの位置を調整する
ax.set_xticks(ticks=ax.get_xticks(),
labels=[i.get_text() + "\n" for i in ax.get_xticklabels()], # 改行を加えてlinespacingが機能するようにする
rotation=45,
ha="right",
linespacing=-3, # 左右位置を調整する
position=(0, 1.5)) # 上下位置を調整する (備考:x軸ではこの第1要素は機能しないので、これでの左右調整はできない)
ax.set_xlabel(ax.get_xlabel(), labelpad=12) # 軸タイトルとの間隔がいまいちなことになるので、調整する
plt.show()
seaborn (with matplotlib)
ほとんどmatplotlibと同じである
plt.figure(figsize=(7, 0.1))
g = sns.barplot(d, x="variable", y="value")
# 45度回転させ、強引にラベルの位置を調整する
g.set_xticks(ticks=g.get_xticks(),
labels=[i.get_text() + "\n" for i in g.get_xticklabels()], # 改行を加えてlinespacingが機能するようにする
rotation=45,
ha="right",
linespacing=-3, # 左右位置を調整する
position=(0, 1.5)) # 上下位置を調整する (備考:x軸ではこの第1要素は機能しないので、これでの左右調整はできない)
g.set_xlabel(g.get_xlabel(), labelpad=12) # 軸タイトルとの間隔がいまいちなことになるので、調整する
plt.show()
plotnine
p9.options.figure_size=(6.5, 1.4) # themeで設定できるが、本質的に不要なコードなので外で記述
(
p9.ggplot(d, p9.aes(x="variable", y="value")) +
p9.geom_col() +
p9.scale_x_discrete(labels=lambda x: [i + "\n" for i in x]) + # 改行を加えてlinespacingが機能するようにする
p9.theme(axis_text_x=p9.element_text(rotation=45,
ha="right",
linespacing=-3, # 左右位置を調整する
margin={"t": -6, "b": 10})) # tで上下位置を調整し、bで軸タイトル位置を調整する
)
plotnineでX軸値がdateやdatetimeの場合
X軸値がdateやdatetimeの場合、以下のような感じで記述する
d2 = pd.DataFrame({"variable": pd.date_range("2025-10-10", "2025-10-17"), "value": range(1, 9)})
p9.options.figure_size=(6.5, 1.4) # themeで設定できるが、本質的に不要なコードなので外で記述
(
p9.ggplot(d2, p9.aes(x="variable", y="value")) +
p9.geom_col() +
p9.scale_x_date(date_breaks="1 days", date_labels="%Y-%m-%d\n") + # 改行を加えてlinespacingが機能するようにする
p9.theme(axis_text_x=p9.element_text(rotation=45,
ha="right",
linespacing=-3, # 左右位置を調整する
margin={"t": -6, "b": 10})) # tで上下位置を調整し、bで軸タイトル位置を調整する
)






