【Python】pandasやscipyを使って気象データ分析

# Pythonを使った気象データ分析 -雨が多いのは何曜日？

「週末は緊張感が切れて、天気も雨になりやすい」なんて聞いたことありませんか？

この記事では、気象庁のデータを利用したその真偽の検証を例題として、Pythonでのデータ分析、可視化手法を紹介します！

## 条件

* もっとも人数の多い東京における降水データを利用
* 過去30年分の降水量について各曜日ごとに合計し、統計的に比較
* 今回、利用、紹介するpythonのツール（ライブラリ）は以下
  * pandas: 表形式(.csv)のデータ分析に利用できるライブラリ (csvファイルの操作に利用)
  * scipy: 科学技術計算に利用できるライブラリ (得られた統計データの検定に利用)

## 統計データの準備

まずは [気象庁のホームページ](https://www.data.jma.go.jp/risk/obsdl/index.php) から東京の過去データのcsvファイルを取ってきます。
ここでは、1992年4月29日から2022年4月29日までのデータを取得して解析を行いました。

実際にダウンロードした.csvファイルをは以下のようなフォーマットをしています。

```python:data.csv
年月日,曜日,降水量の合計(mm),現象なし情報
1992/4/29,水,0,1
1992/4/30,木,37.0,0
1992/5/1,金,0,1
1992/5/2,土,0,1
1992/5/3,日,0.0,0
1992/5/4,月,0,1
1992/5/5,火,0,1
etc...
```

"現象なし情報"の列ですが、気象台では降水量に加え「雨や雪などの降水現象があったかどうか」という「現象の有無の観測」を行っています。
0.5mm以下の降水は、アメダスの降水量の観測単位に達しないため、 "現象なし情報"のフラグで実際の降水の有無が補足情報としてわかるようになっています。
詳しくは気象庁が作成した [初心者向け資料](https://www.wxbc.jp/wp-content/uploads/2019/08/resume-data_all.pdf) をご覧ください。

ただし、今回は単に雨が降ったか降らなかったかの二値ではなく、降水量を目的変数として分析するため、
"現象なし情報"は使わず、3列目の"降水量の合計(mm)"に着目して解析していきます。

## 統計処理の実施1: pandasを利用したcsvデータの加工

では、実際にpandasを使って.csvファイルをpythonで扱いやすい形加工して行きましょう。
まず、.csvファイルをpandasで読み込み、各曜日毎に降水量のリスト変数を作っていきます。

```python:statisctic.py
import pandas

if __name__ == '__main__':
    ## 一行目はヘッダー（見出し行）としてcsvを読み込む
    df = pandas.read_csv('data.csv')

    ## 曜日ごとに以下のような降水量のリストを作成
    ## [0.0, 24.5, 0.0, 6.5, 1.0, 3.5, 0.0, 6.5, 0.0, 0.0, 0.0, 0.0, 0.0, 4.5, ...]
    mon = df.query('曜日 == "月"')['降水量の合計(mm)'].tolist()
    tue = df.query('曜日 == "火"')['降水量の合計(mm)'].tolist()
    wed = df.query('曜日 == "水"')['降水量の合計(mm)'].tolist()
    thu = df.query('曜日 == "木"')['降水量の合計(mm)'].tolist()
    fri = df.query('曜日 == "金"')['降水量の合計(mm)'].tolist()
    sat = df.query('曜日 == "土"')['降水量の合計(mm)'].tolist()
    sun = df.query('曜日 == "日"')['降水量の合計(mm)'].tolist()
```

pandasではオプションなしでcsvを読み込むと、自然と一行目はヘッダー見出しとして認識してくれます。

ここで得られる変数``df``はDataFrameクラスのインスタンス変数になります。
3つの構成要素: ``values``, ``columns``, ``index``による処理を内包したデータ処理に非常に便利なクラスです。

例えば、その次の``df.query('曜日 == "月"')``の処理のように、SQLのようにquery機能が加わっていて、
``曜日``列に``月``の値をもつ行を取り出す、といった処理が簡単に記述できます。

行を曜日でフィルターした後、``降水量の合計(mm)``の列のみを取り出して、``tolist()``でpythonのリストにして解析の準備完了です。

## 統計処理の実施2: scipyを利用した統計データ解析

次に単に曜日ごとの降水量リストを合計します

```python
    ## 曜日ごとの降水合計量を計算
    print('月曜日:', sum(mon), "mm")  # 月曜日: 7266.5 mm
    print('火曜日:', sum(tue), "mm")  # 火曜日: 6802.0 mm
    print('水曜日:', sum(wed), "mm")  # 水曜日: 7137.5 mm
    print('木曜日:', sum(thu), "mm")  # 木曜日: 5766.5 mm
    print('金曜日:', sum(fri), "mm")  # 金曜日: 6824.0 mm
    print('土曜日:', sum(sat), "mm")  # 土曜日: 7461.0 mm
    print('日曜日:', sum(sun), "mm")  # 日曜日: 6705.0 mm
```

これをみると土曜日が一番降水量が多いですね。木曜日が一番少ないです。
週末は雨なイメージが強いという事実が裏付けられました。
これは偶然でしょうか？それとも何か理由があるのでしょうか？

そんな検定をサクッと行ってくれるのがscipyの``stats``ライブラリです。

```python
    from scipy import stats
    result = stats.mannwhitneyu(sat, thu, alternative='two-sided')
    print('p値:', result.pvalue)  # p値: 0.34
```

ここで求めているp値は、低ければ低いほど、統計量がその値となることはあまり起こりえないこと、
つまり、偶然ではないことを意味します。

ここでは一番差の大きい土曜と木曜の降水統計量のp値を見てみたのですが、
34%程度の確率でこれくらいの差は偶然起き得る、ということですので、
土曜日に雨が多いのは、実際には、まあ、今の所はたまたまだろう、といったところでしょう。

## まとめ

* pythonでは pandas や scipy などを利用してデータ分析が簡単に実現できる

以上、ご訪問ありがとうございました。