実現したいこと・前提
・X軸のレイアウトについて
matplotlibのsubplotを用いて、6行2列(計12個)の時系列グラフを作成しております。
それぞれ時系列グラフなので、X軸には日付が出力されます。
YYYY-MM-ddと表示されるのですが、重なってしまい見づらくなってしまうので改善したいです。
・出力サイズについて
6行2列のグラフサイズはそれぞれ、figsize = (15, 50)になっています。
それをsavefigでPDF出力し、更にそれを紙(A4)で印刷します。
それが試行錯誤しても良い感じ?に印刷することができません。
具体的には、1列目のY軸ラベルが表示されなくなったり、
一番下に表示される日付が表示されなくなったりしてしまいます。
これらをある程度、綺麗に印刷できるようにご教示頂きたいです。
宜しくお願い致します。
現在のソースコード
Python
1fig = plt.figure(figsize = (15, 50), tight_layout=True) # グラフサイズ(幅、高さ) 2for col in range(df_1.shape[1]): 3 plt.subplot(12, 2, col+1) 4 plt.plot(df_1.iloc[:, col], marker="o", color="lime") 5 # plt.title("No." + str(col)) # 列Noをタイトル 6 plt.ticklabel_format(style="plain", axis="y", scilimits=(0, 0)) # eを使わない表現 7 plt.gca().get_yaxis().set_major_formatter(ticker.FuncFormatter(lambda v,p: f'{int(v):,d}')) # 3桁ごとにカンマで区切る 8 plt.grid() 9 10 # 列毎(各グラフ)の個別設定 11 for i in range(len(columns)): 12 if col == i: 13 plt.title(columns[i]) 14 plt.legend([columns[i]]) 15 16plt.savefig(str_today + "sample.pdf")
試したこと
figsizeの変更、tight_layoutをやめて個別に設定
補足情報(FW/ツールのバージョンなど)
matplotlib 3.6.3
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答1件
0
ベストアンサー
ChatGPTの回答
Pythonでmatplotlibを利用した以下を実現するサンプルコードを教えてください。
- 折れ線グラフである。
- X軸は10日連続の時系列データである。
- Y軸は10個の1~10程度のランダムな数値データである。
- X軸の軸ラベルの年月日の文字列はお互い重ならないように斜めに傾けて表示したい。
以下がPythonのサンプルコードになります。Matplotlibのpyplotモジュールを使い、X軸のラベルにはtick_params()関数を使い、rotationオプションを指定して斜めに表示させます。
Python
1省略
X軸ラベルの日付文字列がbottomからはみ出しています。bottomに余裕を持たせてください。
X軸のラベルがはみ出さないようにするには、グラフの下部に余白を設定する必要があります。これは、subplots_adjust()関数を使用して実現できます。以下が修正されたサンプルコードになります。
Python
1import random 2import matplotlib.pyplot as plt 3from datetime import datetime, timedelta 4 5# X軸の日付リストを生成 6dates = [datetime(2023, 3, 20) + timedelta(days=i) for i in range(10)] 7 8# Y軸のランダムな数値リストを生成 9values = [random.randint(1, 10) for _ in range(10)] 10 11# 折れ線グラフを作成 12plt.plot(dates, values) 13 14# X軸のラベルを斜めに表示 15plt.xticks(rotation=45) 16 17# グラフのタイトルと軸ラベルを設定 18plt.title('Random Data') 19plt.xlabel('Date') 20plt.ylabel('Value') 21 22# グラフの下部に余白を持たせる 23plt.subplots_adjust(bottom=1.5) 24 25# グラフを表示 26plt.show()
subplotによる複数グラフも考慮して頂けないでしょうか。
宜しくお願い致します。
複数のグラフを表示するには、Matplotlibのsubplot()関数を使用します。以下が、2つのグラフを表示するサンプルコードになります。1つ目のグラフは、上部に表示され、2つ目のグラフは、下部に表示されます。
Python
1省略
ax1のグラフのX軸ラベルが斜めになっていません。ax2と同じく斜めにしてください。
申し訳ありません。ax1のX軸ラベルも斜めにするために、ax1のX軸の目盛りラベルのテキストを回転する必要があります。以下が修正されたサンプルコードになります。
Python
1省略
ax1のX軸ラベルがax2のために隠れてしまっています。ax1とax2の間にも余白を持たせてください。
問題解決のために、plt.subplots_adjust関数を利用して余白を調整しましょう。以下が修正されたサンプルコードになります。
Python
1import random 2import matplotlib.pyplot as plt 3from datetime import datetime, timedelta 4 5# X軸の日付リストを生成 6dates = [datetime(2023, 3, 20) + timedelta(days=i) for i in range(10)] 7 8# Y軸のランダムな数値リストを生成 9values1 = [random.randint(1, 10) for _ in range(10)] 10values2 = [random.randint(1, 10) for _ in range(10)] 11 12# 2つのグラフを表示する 13fig, (ax1, ax2) = plt.subplots(2, 1) 14 15# 1つ目のグラフを作成 16ax1.plot(dates, values1) 17ax1.set_title('Random Data 1') 18ax1.set_ylabel('Value 1') 19 20# 1つ目のグラフのX軸ラベルを斜めにする 21for tick in ax1.get_xticklabels(): 22 tick.set_rotation(45) 23 24# 2つ目のグラフを作成 25ax2.plot(dates, values2) 26ax2.set_title('Random Data 2') 27ax2.set_xlabel('Date') 28ax2.set_ylabel('Value 2') 29 30# X軸のラベルを斜めに表示 31plt.xticks(rotation=45) 32 33# グラフの下部と上部に余白を持たせる 34plt.subplots_adjust(hspace=0.5, bottom=0.2, top=0.9) 35 36# グラフを表示 37plt.show()
惜しい。でもあとは調整すればいいか。
ChatGPTの回答
追加でご回答ありがとうございます。
6行2列(計12個)のグラフをA4一枚に良い感じに印刷する方法はご存じないでしょうか。
宜しくお願い致します。
6行2列の12個のグラフをA4用紙1枚にプリントアウトするには、いくつかのアプローチがあります。ここでは、以下の手順に従って、グリッドを作成してすべてのグラフを1つのFigureにまとめる方法を説明します。
-
1つのFigureを作成します。これは、12個のグラフをまとめるための「コンテナ」になります。
-
Figure内に、6行2列のグリッドを作成します。これにより、12個のサブプロットが作成されます。
-
それぞれのサブプロットに、グラフをプロットします。このとき、適切な位置にプロットするように調整する必要があります。
-
ページの余白を設定し、Figureを印刷可能なサイズに設定します。
-
最後に、Figureを印刷します。
以下がサンプルコードになります。データはランダムな値を使用しています。
python
1import random 2import matplotlib.pyplot as plt 3 4# 6行2列のグリッドを作成し、すべてのサブプロットを取得する 5fig, axs = plt.subplots(nrows=6, ncols=2, figsize=(8.27, 11.69)) 6 7# 各サブプロットにランダムなデータをプロットする 8for ax in axs.flat: 9 # X軸の日付リストを生成 10 dates = [i for i in range(10)] 11 12 # Y軸のランダムな数値リストを生成 13 values = [random.randint(1, 10) for _ in range(10)] 14 15 # ランダムなデータをプロットする 16 ax.plot(dates, values) 17 ax.set_title('Random Data') 18 ax.set_xlabel('X Label') 19 ax.set_ylabel('Y Label') 20 21# ページの余白を設定する 22plt.tight_layout() 23 24# グラフを印刷する 25plt.show()
このコードを実行すると、以下のようにA4サイズの用紙に12個のグラフが印刷されます。
Sample Line Graph with Matplotlib (Multiple Subplots on One Page)
この方法は、サブプロットの数が多くなる場合でも拡張性があり、用紙のサイズを変更するだけでさまざまなページレイアウトを簡単に実現できます。
ChatGPTの回答
更に追加でご回答ありがとうございます。
送って頂いたコードを実行すると、確かにA4一枚に良い感じにプロットされます。
しかし、私が折れ線グラフにしたいデータは、千万・億単位であり桁数が増えているにも関わらず千・百万単位では表示しておりません。
上記のことが原因か分かりませんが、figsizeを同じ値にしてもグラフが小さく表示されてしまいます。
データの桁数が多く、Y軸の値の桁数が増えてしまう場合でも、A4サイズで良い感じに印刷は可能でしょうか。
宜しくお願い致します。
大きな数値を持つグラフを描画する場合、その値が大きいとY軸のラベルの表示スペースが不足してしまい、グラフが小さく表示される可能性があります。この場合、Y軸のラベルの表示スペースを増やすことが必要です。
以下は、Y軸のラベルのスペースを調整する方法です。
python
1import matplotlib.pyplot as plt 2import numpy as np 3 4# データの生成 5x = np.arange(10) 6y = np.random.randint(1, 1000000000, 10) 7 8# グラフの描画 9fig, axs = plt.subplots(6, 2, figsize=(8, 10), constrained_layout=True) 10for i, ax in enumerate(axs.ravel()): 11 ax.plot(x, y) 12 ax.set_title(f'Graph {i+1}') 13 ax.ticklabel_format(axis='y', style='sci', scilimits=(0,0)) # Y軸のラベルを指数表記にする 14 ax.yaxis.get_offset_text().set_fontsize(8) # Y軸のオフセット部分のフォントサイズを設定する 15 ax.tick_params(axis='both', labelsize=8) # 軸ラベルのフォントサイズを設定する 16plt.show()
このコードでは、Y軸のラベルを指数表記にして、Y軸のオフセット部分のフォントサイズを小さくしています。また、軸ラベルのフォントサイズも小さくしています。
このように調整することで、大きな数値を持つグラフでも適切に表示することができます。ただし、グラフが小さくなりすぎてしまう場合は、図のサイズを大きくする必要があります。
何度も回答ありがとうございます。
Y軸の目盛を指数表記せずにA4一枚にプロットすることは可能でしょうか。
宜しくお願い致します。
はい、Y軸の目盛を指数表記せずにA4一枚にプロットすることは可能です。
以下のサンプルコードでは、Y軸の目盛を指数表記せずに、軸のラベルには指数表記を用いるように設定しています。また、グラフのサイズを大きく設定することで、Y軸の値が多くなっても十分なスペースを確保しています。
Python
1import matplotlib.pyplot as plt 2import numpy as np 3 4# 10日分の時系列データを作成 5dates = np.arange('2022-01-01', '2022-01-11', dtype='datetime64[D]') 6 7# 10個の1〜10程度のランダムな数値データを作成 8data1 = np.random.randint(1, 11, size=10) * 10**7 9data2 = np.random.randint(1, 11, size=10) * 10**9 10 11# グラフのサイズを設定 12fig, axs = plt.subplots(nrows=2, ncols=3, figsize=(16, 12)) 13 14# 各グラフを作成 15axs[0, 0].plot(dates, data1) 16axs[0, 0].set_title('subplot 1') 17axs[0, 0].ticklabel_format(style='plain', axis='y') # Y軸の目盛を指数表記せずに表示 18axs[0, 0].set_ylabel('数値 [$10^7$]', rotation='horizontal', labelpad=40) 19 20axs[0, 1].plot(dates, data2) 21axs[0, 1].set_title('subplot 2') 22axs[0, 1].ticklabel_format(style='plain', axis='y') # Y軸の目盛を指数表記せずに表示 23axs[0, 1].set_ylabel('数値 [$10^9$]', rotation='horizontal', labelpad=40) 24 25axs[0, 2].plot(dates, data1) 26axs[0, 2].set_title('subplot 3') 27axs[0, 2].ticklabel_format(style='plain', axis='y') # Y軸の目盛を指数表記せずに表示 28axs[0, 2].set_ylabel('数値 [$10^7$]', rotation='horizontal', labelpad=40) 29 30axs[1, 0].plot(dates, data2) 31axs[1, 0].set_title('subplot 4') 32axs[1, 0].ticklabel_format(style='plain', axis='y') # Y軸の目盛を指数表記せずに表示 33axs[1, 0].set_xlabel('年月日') 34axs[1, 0].set_ylabel('数値 [$10^9$]', rotation='horizontal', labelpad=40) 35 36axs[1, 1].plot(dates, data1) 37axs[1, 1].set_title('subplot 5') 38axs[1, 1].ticklabel_format(style='plain', 39以下略
ChatGPTの回答
何度もご回答ありがとうございます。
これまでの追加情報を整理・追加の要望を書き留めると下記のようになります。
・6行2列の折れ線グラフをA41枚にプロット。
・X軸には、日付(YYYY-MM)が入るが、日付同士が干渉しないように表示させる。
・Y軸には7桁、又は8桁の数値を指数表記せずに表示。又は、千円単位や十万単位で表示させる。
以上です。
これらのことをChatGPTにてコードを作成してもらうことは可能でしょうか。
宜しくお願い致します。
以下が要望に沿ったサンプルコードになります。主に、Y軸目盛のフォーマットを変更することで、指数表記を避けることができます。また、X軸ラベルが重ならないように回転させること、グラフのサイズや余白を調整することにより、6行2列の折れ線グラフをA4 1枚にプロットすることができます。なお、Y軸の単位を適切に設定する必要があります。
python
1import matplotlib.pyplot as plt 2import numpy as np 3import pandas as pd 4from matplotlib.ticker import FuncFormatter 5 6# サンプルデータ 7date_rng = pd.date_range(start='1/01/2022', end='6/30/2022', freq='D') 8data = pd.DataFrame(np.random.randint(1, 100000000, size=(len(date_rng), 12)), columns=[f"col_{i+1}" for i in range(12)]) 9data.set_index(date_rng, inplace=True) 10 11# グラフのフォーマット設定 12plt.rcParams['font.family'] = 'sans-serif' 13plt.rcParams['font.sans-serif'] = ['Arial'] 14plt.rcParams.update({'font.size': 8}) 15 16# グラフのサイズ設定 17fig, axs = plt.subplots(6, 2, figsize=(8.27, 11.69), constrained_layout=True) 18 19# X軸ラベルの回転角度設定 20plt.xticks(rotation=45, ha='right') 21 22# Y軸目盛のフォーマット設定 23def millions_formatter(x, pos): 24 return '{:,.0f}M'.format(x/1000000) 25 26def billions_formatter(x, pos): 27 return '{:,.0f}B'.format(x/1000000000) 28 29# グラフのプロット 30for i, col in enumerate(data.columns): 31 row = i // 2 32 col = i % 2 33 ax = axs[row, col] 34 ax.plot(data.index, data[col], color='blue') 35 ax.yaxis.set_major_formatter(FuncFormatter(millions_formatter)) # 適宜、billions_formatterに変更 36 ax.set_title(col, fontsize=8) 37 ax.tick_params(axis='both', which='major', labelsize=6) 38 ax.set_xlabel('Date', fontsize=8) 39 ax.set_ylabel('Y axis', fontsize=8) 40 41plt.show()
このコードを実行すると、6行2列の折れ線グラフがA4サイズの1枚に収まるようにプロットされます。X軸ラベルの表示も重ならないように回転しています。また、Y軸目盛は、指数表記を避けるために、適切な単位で表示されています。
投稿2023/03/28 08:42
編集2023/04/11 08:31総合スコア38352
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。