前回の記事では、Planet OSからダウンロードした気温の予測データを、Pythonのpandasライブラリを使ってグラフにすることを紹介しました。
今回は気象庁の気温データを利用して、Pythonのpandasライブラリだけでどのような分析ができるかを紹介します。
今年(2018年)の1月の東京は例年よりも寒く感じたので、過去10年間の1月の最低気温データを使って分析してみたいと思います。
気象庁の気象データはこちらから入手できます。
http://www.data.jma.go.jp/gmd/risk/obsdl/index.php
以下の項目を選択して1月の気温データをダウンロードします。
- 「地点の選択」で「東京」
- 「項目を選ぶ」で「日別値」で「日最低気温」
- 「期間を選ぶ」の「特定の期間を複数年分、表示する」で過去10年間の1/1から1/31までの期間
データは「data.csv」というファイル名のCSV形式で保存されます。
CSVファイルをpandasのDataFrame形式に読み込む
このCSVファイルをpandasのDataFrame形式に読み込みます。
CSVファイルを読み込む際、エラーにならないよう文字コードはShift JISを指定します。
また、データを容易に扱えるよう不要なヘッダ行は削除し、年月日のデータはインデックス列に移動させます。
# pandasライブラリをインポートします。 import pandas as pd # CSV形式のファイルをpandasのデータフレーム形式に読み込みます。 # skiprows : 先頭から1、2、3、5、6行目のデータは読み込みません。 # encoding : 文字コードはShift JISを指定します。 # index_col : 日付をインデックスにします。 df = pd.read_csv( "data.csv", skiprows=[0,1,2,4,5], encoding='shift_jis', index_col=0 ) # どのように読み込まれたかを先頭5行を表示して確認します。 df.head()
最低気温(℃) | 最低気温(℃).1 | 最低気温(℃).2 | |
---|---|---|---|
年月日 | |||
2008/1/1 | 1.8 | 8 | 1 |
2008/1/2 | 1.1 | 8 | 1 |
2008/1/3 | 1.5 | 8 | 1 |
2008/1/4 | 2.7 | 8 | 1 |
2008/1/5 | 4.0 | 8 | 1 |
「最低気温(℃).1」列は品質情報、「最低気温(℃).2」列は均質番号のため、分析に必要がない情報として削除します。
df = df.drop( df.columns[[1,2]], axis=1 ) df.head()
最低気温(℃) | |
---|---|
年月日 | |
2008/1/1 | 1.8 |
2008/1/2 | 1.1 |
2008/1/3 | 1.5 |
2008/1/4 | 2.7 |
2008/1/5 | 4.0 |
年月日の操作を行いやすくするため、datetime64形式に変換します。
df.index = pd.to_datetime( df.index ) df.head()
最低気温(℃) | |
---|---|
年月日 | |
2008-01-01 | 1.8 |
2008-01-02 | 1.1 |
2008-01-03 | 1.5 |
2008-01-04 | 2.7 |
2008-01-05 | 4.0 |
DataFrame形式の気温データをグラフで視覚化する
DataFrameのplotメソッドを使ってDataFrameの最低気温データをグラフで視覚化します。
最初にJupyter Notebook内でグラフを表示させるためのマジックコマンドを実行します。
%matplotlib inline
このままplotメソッドを呼び出すと、1つのグラフに各年の気温データが横に並んで表示されます。
また、凡例と横軸にはDataFrameのヘッダーが表示されます。
凡例は「最低気温(℃)」、横軸は「年月日」ですが、日本語のため文字化けして□が表示されます。
df.plot()
このままでは、各年の気温データの比較が難しいので、各年の気温データを重ねて表示させます。
各年ごとにplotメソッドを呼び出してplotメソッドのaxパラメーターに格納していくと、各年の気温データを重ねて表示できます。
また、DataFrmeの列タイトル「最低気温(℃)」とインデックスタイトル「年月日」をそれぞれ「January」と各年の西暦に変更して文字化けを解消します。
<参考> 日本語の文字化けは、matplotlibライブラリをインポートしてフォントを設定することで解消できます。
# axパラメーターを初期化します。 ax = None # インデックスのタイトルを「年月日」から「January」に修正します。 df.index.name = "January" # 2009年から2018年まで各年ごとにplotメソッドを呼び出します。 for year in range( 2009, 2018 + 1 ): # 気温データを年ごとに抽出します。 df_year = df[df.index.year==year] # 横軸が日にちのみとなるようDataFrameを変更します。 df_year.index = df_year.index.day # 列名を「最低気温(℃)」から各年の西暦に変更し、グラフの凡例に表示させます。 df_year.columns = [year] # axパラメーターplotメソッドを呼び出します。 ax = df_year.plot( ax=ax, figsize=(8, 5), fontsize=10 )
各年の気温データを重ねて表示することができました。
しかし、線が重なりが多く確認が難しいので、2018年の気温データだけ他の年と異なる色にしたグラフを作成してみます。
最後のplotメソッドを呼び出す処理だけを上記の処理から変更しています。
# axパラメーターを初期化します。 ax = None # 2009年から2018年まで各年ごとにplotメソッドを呼び出します。 for year in range( 2009, 2018 + 1 ): # 気温データを年ごとに抽出します。 df_year = df[df.index.year==year] # 横軸が日にちのみとなるようDataFrameを変更します。 df_year.index = df_year.index.day # 列名を「最低気温(℃)」から年に変更し、グラフの凡例に表示させます。 df_year.columns = [year] # axパラメーターplotメソッドを呼び出します。 if year == 2018: # 2018年のデータを赤(red)で表示します。 ax = df_year.plot( ax=ax, figsize=(8, 5), fontsize=10, c='r') else: # 2018年のデータを黄色(yellow)で表示します。 ax = df_year.plot( ax=ax, figsize=(8, 5), fontsize=10, c='y')
DataFrameの構造を変更する
今のDataFrameの構造はずべての年の気温データが1つの列の中にあります。
各年の気温データを各列にわけることで、plotメソッドを1回呼び出すだけで、各年の気温データを重ねて表示できます。
# プログラム上で正しく列名を認識させるため、列名を「最低気温(℃)」から「temperature」に変更します。 df.columns = ["temperature"] # 各年の気温データが複数列になるDataFrameを作成します。 for year in range( 2009, 2018 + 1): if year == 2009: # 2009年のデータでDataFrameを新規に作成します。 df_multi = pd.DataFrame({2009:df[df.index.year==year].temperature} ) # 「年月日」を2010年から2018年のデータが追加できるように日にちのみに変更します。 df_multi.index = df_multi.index.day else: # 一度、仮のDataFrameに読み込み、「年月日」列を削除します。 df_tmp = pd.DataFrame({'temperature':df[df.index.year==year].temperature} ) df_tmp.index = df_tmp.index.day # 2009年のDataFrameに2010年から2018年の気温データを追加します。 df_multi[year] = df_tmp.temperature df_multi.head()
2009 | 2010 | 2011 | 2012 | 2013 | 2014 | 2015 | 2016 | 2017 | 2018 | |
---|---|---|---|---|---|---|---|---|---|---|
January | ||||||||||
1 | 1.6 | 0.2 | 2.2 | 2.9 | 3.0 | 3.1 | 0.7 | 3.6 | 2.0 | 0.4 |
2 | 3.1 | 0.9 | 4.1 | 3.0 | 4.2 | 3.1 | -2.2 | 2.6 | 3.8 | 0.8 |
3 | 2.0 | 1.4 | 3.1 | 3.8 | 1.8 | 3.8 | -1.1 | 3.0 | 3.5 | 2.3 |
4 | 4.3 | 3.7 | 3.3 | 2.0 | 1.0 | 2.4 | -0.4 | 4.4 | 3.6 | 0.0 |
5 | 5.6 | 3.0 | 2.8 | 1.9 | 0.2 | 3.9 | 1.3 | 5.1 | 3.7 | 0.8 |
この構造にDataFrameを変更することで、plotメソッドを1回の呼び出すだけで、各年の気温データを重ねて表示できます。
# plotメソッドを呼び出します。 df_multi.plot( figsize=(8, 5), fontsize=10 )
同様に、2018年の気温データだけ異なる色にしたグラフを作成します。
# axパラメーターを初期化します。 ax = None for year in range( 2009, 2018 + 1 ): if year == 2018: ax = df_multi[year].plot( figsize=(8, 5), fontsize=10, c='r') else: ax = df_multi[year].plot( figsize=(8, 5), fontsize=10, c='y')
折れ線グラフ以外のグラフを作成する
折れ線以外のグラフを作成して過去10の気温データを分析します。
- 棒グラフ
各日付ごとに10年分の気温が描画されてしまいます。これではデータの比較ができません。
- 箱ひげ図
箱ひげ図は、最小値、第1四分位点、中央値、第3四分位点、最大値で構成されます。
丸は外れ値となります。
箱ひげ図では、2018年は他の年よりも気温が低くなっていることがわかります。
<外れ値とは> ひげの長さを四分位範囲(IQR)の1.5倍を上下限としたとき、「第一四分位数-1.5×IQR」がひげの下限、「第三四分位数+1.5×IQR」がひげの上限となり、ひげの下端より小さい値やひげの上端より大きい値が「外れ値」となります。
df_multi.plot( kind='box', figsize=(8, 5), fontsize=10 )
- ヒストグラム
各気温が出現する回数が描画されます。
ヒストグラムからは2018年が他の年よりも気温が低いことは、読み取れませんが、過去10年において1月の最低気温は2度から4度になる回数が多いことがわかります。
# alphaはグラフの透過率です。 df_multi.plot( kind='hist', figsize=(8, 5), fontsize=10, alpha=0.5 )
- カーネル密度推定
ヒストグラムよりも各年ごとの温度の出現頻度がわかります。
2018年は他の年よりも低い気温の日が多いことがわかります。
df_multi.plot( kind='kde', figsize=(8, 5), fontsize=10 )
- 散布図
横軸を日付にし、縦軸に各年の気温データをプロットした散布図を作成しました。
2018年の気温は赤でプロットしています。
縦軸のタイトルは最後にプロットした年が表示されています。
折れ線グラフと同じような見え方となります。
# 散布図の場合はインデックスを軸にできないため、インデックスを「January」列として追加します。 df_multi['January'] = df_multi.index # axパラメーターを初期化します。 ax = None for year in range( 2009, 2018 + 1 ): if year == 2018: ax = df_multi.plot( kind='scatter', ax=ax, x="January", y=year, figsize=(8, 5), fontsize=10, c='r') else: ax = df_multi.plot( kind='scatter', ax=ax, x="January", y=year, figsize=(8, 5), fontsize=10, c='y') # 散布図のプロットが完了したので、最初に追加した「January」列は削除します del df_multi['January']
平均最低気温と偏差
各年ごとの平均気温と気温の標準偏差(ばらつき)をグラフにして分析します。
# 各年の最低気温の平均をグラフにします。 df_multi.mean().plot( kind='bar')
# 各年の最低気温の標準偏差をグラフにします。 df_multi.std().plot( kind='bar' )
平均の最低気温は2018年は他の年よりも1〜2℃低いことがわかります。
気温のばらつきは2018年が最も高く、1月の中で寒暖の差が大きかったようです。
まとめ
pandasライブラリだけでDataFrameの値をそのまま色々な形のグラフにしたり、平均値や標準偏差を計算してその結果を直接グラフにできることがわかりました。
あなたも、Avintonでこのような最先端技術を習得し活用してみませんか?
社員の成長を導きながら、AIやビッグデータなどの最先端技術をプロジェクトに活用していくことが私たちのビジョンです。Avintonの充実した技術研修でスキルアップを図り、あなたのキャリア目標を一緒に達成しませんか?