質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

562閲覧

plt.plotで特定の範囲に絞ってグラフを作成したいが、出力したグラフが歪んでしまう

humanbeing

総合スコア7

Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2022/03/05 10:54

編集2022/03/05 10:55

1980年,1990年,2000年,2010年,2020年の平均気温変化をグラフで表したい

こんにちは。

気象動向をスクレイピングで調査しており、10年ごとの月別平均気温の変化をグラフで可視化しようとしております。

皆様の協力あってスクレイピング自体はうまくいったのですが、1990年以降のグラフをうまく可視化することができないという問題に直面しました。X軸の設定は調整できているのですが、Y軸の設定がうまくいきません。逆にY軸をいじろうとすると、かえってX軸の範囲がおかしくなってしまい、どのように対処すればよいのかお伺いできればと思います。

グラフの作り方もまだ勉強中ですので、もっとシンプルな方法がある、このライブラリを使うべき、などのご意見がありましたら、是非参考にさせて頂きます。

よろしくお願いいたします。

コード、CSVはgithubの方にもアップロードしておきます。(追記:URLの間違いを訂正)
https://github.com/yamaplay/Weather_scr_avg

2000年のグラフが歪んでしまう

まず正しいグラフがどのようなものかが把握できないと思いますので、エクセルで作成した2000年のグラフをご覧ください。

イメージ説明

下記のコードを実行すると、このようなグラフになってしまいます。原因ですが、おそらく私がコードや範囲指定を誤っているせいだと思います。

グラフは正しいが、横軸がおかしい

横軸は正しいが、グラフは1980年のまま

ソースコード

import requests from bs4 import BeautifulSoup import csv place_name = ["札幌", "秋田", "新潟", "東京", "大阪", "広島", "高知", "熊本", "那覇"] place_codeA = [14, 32, 54, 44, 62, 67, 74, 86, 91] place_codeB = [47412, 47582, 47604, 47662, 47772, 47765, 47893, 47819, 47936] base_url = "http://www.data.jma.go.jp/obd/stats/etrn/view/monthly_s1.php?prec_no=%s&block_no=%s&year=%s&month=1&day=1&view=p1" def str2float(str): try: return float(str) except: return 0.0 if __name__ == "__main__": for place in place_name: All_list = [['年月', '降水量(mm)', '日の平均気温(℃)', '日の最高気温(℃)', '日の最低気温(℃)', '最高気温(℃)', '最低気温(℃)']] print(place) index = place_name.index(place) for year in range(1980, 2021): print(year) r = requests.get(base_url%(place_codeA[index], place_codeB[index], year)) r.encoding = r.apparent_encoding soup = BeautifulSoup(r.text) rows = soup.findAll('tr',class_='mtx') rows = rows[3:] for row in rows: data = row.findAll('td') rowData = [] #初期化 rowData.append(str(year) + "/" + str(data[0].string)) rowData.append(str2float(data[3].string)) rowData.append(str2float(data[7].string)) rowData.append(str2float(data[8].string)) rowData.append(str2float(data[9].string)) rowData.append(str2float(data[10].string)) rowData.append(str2float(data[11].string)) All_list.append(rowData) with open(place + '.csv', 'w') as file: writer = csv.writer(file, lineterminator='\n') writer.writerows(All_list) import matplotlib.pylab as plt import pandas as pd df=pd.read_csv('熊本.csv', encoding="SHIFT_JIS") h1, =plt.plot(df['日の平均気温(℃)'][0:12],label='1980/1~1980/12') plt.xticks(range(12),df['年月'][0:12],rotation=90,size='small') plt.legend(handles=[h1]) plt.show()#1980年のものはきれいに出力される df=pd.read_csv('熊本.csv', encoding="SHIFT_JIS") h2, =plt.plot(df['日の平均気温(℃)'][240:252],label='2000/1~2000/12') plt.xticks(range(12),df['年月'][240:252],rotation=90,size='small') plt.legend(handles=[h2]) plt.show()#こちらはグラフ自体は正しく出ているが、うまく描画できていない。 df=pd.read_csv('熊本.csv', encoding="SHIFT_JIS") h2, =plt.plot(df['日の平均気温(℃)'][0:12],label='2000/1~2000/12') plt.xticks(range(12),df['年月'][240:252],rotation=90,size='small') plt.legend(handles=[h2]) plt.show()#グラフは当然1980年のものになってしまう

補足、参考

参考にしているサイトは以下の通りです。
Pythonの覚え書き(グラフのプロット編)
https://hirotaka-hachiya.hatenablog.com/entry/2015/12/29/123142

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

まず、CSV ファイルを読み込むのは一度だけにします。その際、「年月」のカラムを datetime 型にしてインデックスとして読み込みます。datetime 型にしておけば df.index.year==1980 などと指定して必要なデータを抽出することができます。

python

1import matplotlib.pylab as plt 2import pandas as pd 3from matplotlib import dates as mdates 4 5plt.rcParams['font.family'] = 'MS Gothic' 6 7df = pd.read_csv('熊本.csv', parse_dates=['年月'], index_col='年月') 8fig, axes = plt.subplots(3, 2, figsize=(10, 10)) 9axes = axes.flatten() 10years = range(1980, 2021, 10) 11for year, ax in zip(years, axes): 12 df[df.index.year==year].plot( 13 y = '日の平均気温(℃)', x_compat=True, xlabel='', 14 label=f'{year}/1~{year}/12', title=f'{year}年 平均気温(℃)', ax=ax) 15 ax.set_ylim([0., 32.]) 16 ax.xaxis.set_tick_params(reset=True) 17 ax.xaxis.set_major_locator(mdates.MonthLocator()) 18 ax.xaxis.set_major_formatter(mdates.DateFormatter('%-m月')) 19 ax.grid(axis='y') 20 ax.legend(loc='upper left') 21 ax.tick_params(top=False) 22 ax.set_frame_on(False) 23 24# 余りは非表示 25axes[-1].axis('off') 26 27fig.tight_layout(pad=2.0) 28plt.show()

イメージ説明

投稿2022/03/05 13:37

編集2022/03/06 01:14
melian

総合スコア19883

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

humanbeing

2022/03/06 07:44

melianさん、回答ありがとうございます。 グラフがとても綺麗で感動しました!タイトルやラベル、横軸の単位なども丁寧に付け加えてあり、とても読みやすいです。ありがとうございます。 いくつか実行する時にエラーが出た為、encoding ="SHIFTJIS"で読み込んで、Invald format stringエラーは ('%-m月')の部分を('%#m月')と変更することで改善できました。LinuxとWindowsでは少し異なるようですね。(参考にしたサイト:https://kuttsun.blogspot.com/2022/02/python-datetime-strftime-invalid-format.html) 改めまして回答ありがとうございます。
guest

0

df['日の平均気温(℃)'][240:252] を表示すると

240 7.0 241 5.3 242 10.3 243 15.0 244 20.0 245 23.4 246 28.1 247 28.3 248 24.7 249 20.3 250 14.2 251 8.5

と出るので、x 座標 240 〜 251 のところにグラフが表示されてるんだと思います。

これを、x 座標 0 〜 11 のところにグラフを表示すればいいので、plt.plot の引数の先頭に range(12) を追加して次のようにすれば良いのでは。

diff

1h2, =plt.plot(range(12),df['日の平均気温(℃)'][240:252],label='2000/1~2000/12')

イメージ説明

投稿2022/03/05 12:45

hoshi-takanori

総合スコア7895

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

humanbeing

2022/03/06 07:49

hoshi-takanoriさん、回答ありがとうございます。 なるほど、x 座標 240 〜 251の箇所にグラフがあったために歪んでしまっていたのですね、原因がわかってスッキリしました。plt.plotの先頭にrangeをつけて範囲を調整するというのも手軽で、今後matplotlibで作図するときに役立ちそうです。 ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問