【matplotlib】(縦棒グラフ+散布図)Excelで作るようなデザインのグラフを作りたい【python】

pythonでグラフを作るとき、自分好みのデザインにするのにいつも苦労する。

seabornもおしゃれでいいのだけど、みんなが使いすぎていてpython感が出すぎるので、Excelで作ったみたいなデザインにするにはどうするかを頑張ってみた。

今後自分のメモ用にいくつかのパターンを作ってみたいと思う。

 

今回はこの縦棒グラフ+散布図。前回横棒グラフで作ったので今回は縦棒グラフ。上側の散布図は線でつないでみた。

 

import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
import matplotlib.gridspec as gridspec

#データ
sales_1 = np.array([153, 202, 355, 430])#棒グラフのデータ
sales_2 = np.array([53, 78, 100, 158])#棒グラフのデータ
profit = sales_2 / sales_1 * 100#散布図のデータ
labels = ['Q1', 'Q2', 'Q3', 'Q4']#x軸のラベル
ind = np.arange(len(sales_1)) #要素の数

#色
c_1 = '#cccccc'#棒グラフ用。濃いグレー
c_2 = '#444444'#棒グラフ用。薄いグレー
c_3 = "#d94d51"#散布図用。赤い色
c_gray = "#444444" #軸の色
c_gray2 = "#cccccc"#薄いグレー

#サイズ
label_s1 = 15#文字サイズ

#グラフサイズ
fig_x = 6
fig_y = 8

fig = plt.figure(figsize=(fig_x,fig_y),facecolor='#ffffff')#グラフの作成

# gridspecを初期化し、2つの行を定義。ここで行の横幅を指定。
gs = gridspec.GridSpec(2,1, height_ratios=[1, 3])  # 3:1の横幅の比率でサブプロットを配置
ax1 = fig.add_subplot(gs[0])#subplotの作成(左側)
ax2 = fig.add_subplot(gs[1])#subplotの作成(右側)

#フォント指定
plt.rcParams['font.family'] = 'Meiryo'

#横棒グラフ
bar_w = 0.5 #棒グラフの太さ
p1 = ax2.bar(ind, sales_1, color=c_1, label='売上', width=bar_w)#横棒グラフ
p2 = ax2.bar(ind, sales_2, color=c_2, label='営業利益', width=bar_w)#横棒グラフ

#散布図
s_size = 100 
s_lw = 2
ax1.plot(ind, profit, color=c_3, linestyle='-', zorder=1)
s1 = ax1.scatter(ind, profit, color=c_3, s=s_size, facecolor="white", linewidth=s_lw, label='営業利益率', zorder=2)

#x軸
x_ticks_space = 0.75
x_ticks = [ind[0]-x_ticks_space, ind[-1]+x_ticks_space]#x軸のスペースを調整
#ax1-y軸
ax1.set_xlim(x_ticks[0], x_ticks[1])#y目盛の範囲
ax1.tick_params(axis='x', which='both', bottom=False, top=False)#xticksの目盛を消す
ax1.set_xticks(ind)
ax1.set_xticklabels(labels, fontsize=0, color=c_2)#x軸のラベルの設定(fontsize=0にして文字を消す)
#ax2-x軸
ax2.set_xlim(x_ticks[0], x_ticks[1])#x目盛の範囲
ax2.tick_params(axis='x', which='both', bottom=False, top=False)#xticksの目盛を消す
ax2.set_xticks(ind)
ax2.set_xticklabels(labels, fontsize=label_s1, color=c_2)#x軸のラベルの設定

#ax2-y軸
y_ticks = [0,450]#軸ラベルの値
y_ticks_l = [0,100,200,300,400]
grid_w = 1
ax2.set_ylabel("売上, 営業利益(億円)", fontsize=label_s1, fontfamily = 'Meiryo', color=c_2, labelpad=10)#軸ラベル
ax2.set_ylim(y_ticks[0], y_ticks[1])#x目盛の範囲
ax2.set_yticks(y_ticks_l, color=c_2)#x軸目盛線の設定
ax2.set_yticklabels(y_ticks_l, fontsize=label_s1, color=c_2)#x軸目目盛ラベルの設定
ax2.grid(axis="y", lw=1, c=c_gray2)#x軸目盛線をありに
#枠線を消す
spine_w = 1
ax2.spines['top'].set_linewidth(0)
ax2.spines['bottom'].set_linewidth(spine_w)
ax2.spines['bottom'].set_color(c_2)
ax2.spines['left'].set_linewidth(spine_w)
ax2.spines['left'].set_color(c_2)
ax2.spines['right'].set_linewidth(0)

#ax1-y軸
y2_ticks = [25,45]#軸ラベルの値
y2_ticks_l = [30,35,40]
grid_w = 1
ax1.set_ylabel("営業利益率 %", fontsize=label_s1, fontfamily = 'Meiryo', color=c_3, labelpad=10)#x軸ラベル
ax1.set_ylim(y2_ticks[0], y2_ticks[1])#x目盛の範囲
ax1.set_yticks(y2_ticks_l, color=c_3)#x軸目盛線の設定
ax1.set_yticklabels(y2_ticks_l, fontsize=label_s1, color=c_3)#x軸目目盛ラベルの設定
ax1.grid(axis="y", lw=1, c=c_gray2)#x軸目盛線をありに

#枠線を消す
spine_w = 1
ax1.spines['top'].set_linewidth(0)
ax1.spines['bottom'].set_linewidth(0)
ax1.spines['left'].set_linewidth(spine_w)
ax1.spines['left'].set_color(c_2)
ax1.spines['right'].set_linewidth(0)

# 売上の数値を棒グラフの上に表示
text_s = 15
for rect in p1:
    height = rect.get_height()
    ax2.text(rect.get_x() + rect.get_width()/2., height + 5,
            '%d' % int(height), ha='center', va='bottom', color=c_gray, fontweight='bold', fontsize=text_s)
    
for rect in p2:
    height = rect.get_height()
    ax2.text(rect.get_x() + rect.get_width()/2., height - 30,
            '%d' % int(height), ha='center', va='bottom', color="#ffffff", fontweight='bold', fontsize=text_s)

# 営業利益率の数値を棒グラフの上に表示
for n in ind:
    ax1.text(n+x_ticks_space/2, profit[n]+4, 
            '%d' % int(profit[n])+"%", ha='right', va='center', color=c_3, fontweight='bold', fontsize=label_s1)
    
#xticksの目盛線を消す
ax1.tick_params(axis='both', which='both', bottom=False, top=False, left=False, right=False, color=c_2)#x1軸
ax2.tick_params(axis='both', which='both', bottom=False, top=False, left=False, right=False, color=c_3)#x2軸
#軸を背面に移動
ax1.set_axisbelow(True)
ax2.set_axisbelow(True)

#凡例

ax1.legend(loc='lower left', fontsize=label_s1, bbox_to_anchor=(0,-0.1), labelcolor=c_3, facecolor='white', framealpha=1, frameon=True, edgecolor="white")#散布図の凡例
ax2.legend(loc='lower left', fontsize=label_s1, bbox_to_anchor=(0, 0.8), labelcolor=c_gray, facecolor='white', framealpha=1, frameon=True, edgecolor="white")#棒グラフの凡例