1.時系列データの解析(データの読み込み・切り出し・簡単な作図)

1.0 はじめに

1.1 データの読み込み:csvファイル(アメダスデータ)を読み込む

1.2 データを切り出す

$\ \ \ $1.2.1. インデックスで範囲指定

$\ \ \ $1.2.2. 条件で指定

1.3 絵を描く


1.0 はじめに

 本演習では、気象観測データを用いて簡単な統計解析と結果の描画の実習を行う。  前半(1、2章)では一次元時系列データ(気象庁AMeDASデータ)を、後半(3章)では四次元データ(NCEP/NCAR大気再解析データ)を用いる。  解析にはPythonを用いる。フリーで気軽に導入できること、各種データ解析用のライブラリが充実していることなどから最近各分野で急速に普及しており、地球科学分野においても例外ではない。

 本HPでは気象データの解析を題材に話を進めるが、Pythonの基礎については以下のサイトに非常に良く まとめられているので是非参考にされたい:

 また、気象データの描画方法については以下に詳しい:

 既に述べたように、Pythonにはデータ処理・解析の目的に応じて多種多様なライブラリが用意されている。 この章では、以下のライブラリを使って簡単な描画と統計解析を実践してみる(他にも色々とあるので 興味がある人は自分で調べてみてください)。

 ただし、これらはPythonでの最も基本的な解析ツールであり、他にも目的に応じて様々なライブラリが提供されている。 解析・描画には幾通りもやり方があるので、興味がある人は各自で調べて色々と試してみてほしい。


1.1 CSVデータの読み込み(pandas)

 時系列データ(1次元)の解析として、表形式のデータである気象庁アメダスデータ(data/AMeDAS/Kyoto/Kyoto_***.csv)を用いる(データは気象庁HP (過去の気象データ検索)から取得した)。

 なお、生の観測データには欠損値や異常値が含まれることがしばしばある。これらの処理については(1980年以降のAMeDASデータを扱う分には必要ないはずだが)別途こちら(A.データの品質管理)にまとめたので興味があれば参照されたい。


◆ DataFrame と Series について

 Excelで見慣れていることと思うが、csvデータはにもにもインデックス(ラベル)を持った二次元のデータである(下図を参照;この例では、行のインデックスが日付、列のインデックスが観測変数)。このようなデータ構造をpandasではDataFrameという。これに対して、列or行の一方のみインデックスを持つ一次元のデータ構造をSeriesという。

Linux端末では、Excelの代用としてLibreOfficeが使えるのでファイルを開いて眺めてみると良い。 コマンド例:

$libreoffice (ファイル名)

 pandasでデータを読み込むと、一つ一つのデータにインデックスが「タグ付け」される。以下に示すように、これらインデックスの値・範囲を指定することによって、データの一部を適宜切り出して描画・解析に用いることができる。

 また、時系列データを解析しやすいように時間方向のインデックスDateTime型(日時・時刻形式)として読み込んでおくと便利である。こうすることで、後に示すように月や曜日を指定してデータを抜き出すことが可能となる(これはデータ解析で大きな利点である!)。

Drawing


【準備】 複数のファイルを結合して長期時系列データを作る

 1年分1つのファイルになっているので、複数のファイルの中身を結合して、長期の時系列データセットを作って以降の解析に用いる。

◯ [関数] pandas.read_csv (csvファイルの読み込み)

ここでは、pandasの関数であるread_csvを使ってcsvファイルを読み込んでいる。

  • 使い方: pandas.read_csv(ファイル名,オプション)

  • オプションの説明

    • encoding =: 文字コードの指定(ファイルの文字コードはコマンドラインで$nkf --guess (ファイル名)として調べられる。)
    • header =: のインデックス(e.g.,観測変数)がファイルの何行目にあるかを指定する(0から数え始めることに注意!)。
    • index_col =: インデックス(e.g.,日付)がファイルの何列目にあるかを指定する。
    • parse_date =: インデックスを「日時」の型として読み込む場合にその列を指定する。リストとして指定(e.g.,[0])。
    • ..

※ 色々なオプションが付いていて複雑ですが、観測データの解析ではデータの読み込みに苦労することが多いです。上に示したプログラム例も、私がそれなりに試行錯誤した結果です(ので安心してください...?)。何もオプションをつけずに実行するとどうなるか、確認してみるとよいです。

◯ [関数] pandas.concat (データの結合)

  • 使い方: pandas.concat([ファイル1, ファイル2, ....], オプション)

  • オプションの説明:

    • axis=: データを連結させる方向(0:行方向、1:列方向)。デフォルトは0
    • join=: inner: 共通する部分があるものだけ抜き出す。outer:和集合をとる(一方のインデックスにしかデータが無い場合は、他方には>Nanが入る)
    • key=: (列方向に連結する場合)行のインデックスを設定する。

1.2 データの切り出し

 これで(綺麗に)データを読み込むことができた。以下、必要に応じてデータを切り出して解析・描画する。まずはデータの切り出しについて、「1.2.1 インデックスで範囲指定する方法」と「1.2.2 条件指定する方法」の二つを学ぶ。

1.2.1 インデックスで範囲指定

 先にも説明したように、Pandasで扱うオブジェクトは各データにインデックスがタグ付けされている。これを活かして、インデックスで範囲指定して切り出すのが楽である。

◆ インデックスの参照(.index, .columns): どんなインデックスが定義されているか?

 まずはどんなインデックスがあるか調べよう。これは以下のようにすればよい:

 ※ 今回はデータを読み込む際にparse_dateのオプションを付けたので、行のインデックスはDatetimeIndexという、日付に関する処理を容易に行えるインデックス(型)になっている。


◆ データの切り出し(スライシング): インデックスで範囲指定

どんなインデックスがあるか分かったので、これらの範囲を指定してデータを切り出すことができる。

(a) インデックス名(ラベル名)を指定して切り出し: .loc[] (オススメ)

(b) インデックスの位置(整数)を指定して切り出し: .iloc[]

時刻で範囲指定してみる

特定の年月 のデータを切り出すことも可能である


1.2.2 データの切り出し(スライシング): 条件をつけて切り出す

 上ではある範囲のデータを丸ごと取り出したが、データ解析ではある条件を満たすデータのみを切り出したい場合がある。この時便利なのが真偽値配列(bool型)を用いた方法である。これは次のようにすれば良い:

  1. ある条件を設定して、真偽値配列(True, Falseのみからなる配列)を作る
  2. データ行列に真偽値配列を作用させ、Trueの要素のみを抜き出す

 これは実例を示すのが早いだろう。

【練習課題】「2021年01月に日平均気温が氷点下だった日を抽出せよ」

【練習課題】「2021年に猛暑日になった日を抽出せよ」


1.3 図の描画:

 最後に描画である。 pandasオブジェクトには、絵を描くメソッドが用意されている。まずはこれを使って簡単に図を描いてみよう(1.3.1節)。続いてmatplotlibを用いた一般的な描画方法を実習して体裁を整える方法を学ぶ(1.3.2節)。

※ 実際の(私の)研究では、データ解析の段階ではなるべくメソッドを用いて素早く沢山の図を描き(その分結果の吟味に時間をかける)、論文化の(人に見せる)段階で細部にこだわった図を描く、といったように両者を使い分けている。

1.3.1 pandasのメソッドを使う 〜お手軽プロット〜

  pandasではデータにインデックスがタグ付けされているため、これらを軸情報としてお手軽に図を描くことができる。以下は代表例で、他にも色々とあるので興味があれば各自で調べてみてください。

◆ ラインプロット

◆ ヒストグラム

◆ 散布図


1.3.2 図の描画: matplotlib を用いる(より汎用性の高い描画方法)

   matplotlibは他の描画ライブラリのベースとなっていることが多く、数値配列全般について(Pandasの形式でなくても)プロットできるので、何かと応用が効く(実際、pandasの描画メソッドは内部においてmatplotlibを呼び出している)。

以下のプログラムではmatplotlib.pyplot関数をpltとして参照している。大まかな流れとしては、紙(1)と描画領域(2)を準備し、そこにグラフをプロットし(3)、必要であれば軸を追加したり体裁を整える(4)。

◆ 図の書き方の手順

  1. 紙を用意: fig = plt.figure(figsize=(a,b))

    • figsize: 横-縦の比率(a:b)
    • ..
  2. 図を描く領域(サブプロット領域)を用意(複数作ることもできる): ax = fig.add_subplot(l,m,n)

    • (l,m,i): l(縦) x m(横) 個の領域を作って、そのうちi個目の領域
  3. サブプロット領域にグラフを描く:

    • ax.plot(x,y,color=,label=,linewidth=,linestyle=...) : ラインプロット
    • ax.bar(x,y,color=,label=,...) : 棒グラフ
    • ax.scatter(x,y):散布図
    • ax.hist(x,y,alpha=,...):ヒストグラム
    • ....
  4. 体裁を整える(軸、ラベル、タイトルなど): ax.set_xlabel() etc.

    • ax.set_xlabel('ラベル',fontsize=,color=), ax.set_ylabel('ラベル'): x軸, y軸のラベル
    • ax.set_xtitle('タイトル',fontsize=,color=,..),ax.set_ytitle('タイトル'): x軸, y軸のタイトル
    • ax.set_xlim([xmin,xmax]),ax.set_ylim([ymin,ymax]): x軸,y軸の範囲を設定
    • ax.tick_params(axis=,direction=,colors=,labelsize=,...) :目盛りの書式を設定
    • ax.legend(): 凡例を描く. plot関数で設定したlabelが書かれる
    • ax.set_title('タイトル'):サブプロットのタイトル
    • fig.suptitle('タイトル'):フィギュアのタイトル
    • .....
  5. 図を保存する場合: plt.savefig(ファイル名)

  6. 図を画面表示!: plt.show()

注1)1, 2は以下のようにまとめてもよい:

注2)plotの引数には、リストや配列(ndarray型)だけでなく、pandasデータ(Series型)をそのまま渡すこともできる。


【参考】左右に軸を描く: ax.twinx()

単位の異なる二つの物理量を一枚の絵に表したい場合に使う。