膨大な時系列データを月(日)毎に抽出しCSVで出力する

こんにちは。システムソリューション部のgoppyです。
お盆は立山に行ってきました。36座目の日本百名山です。

さて、現在、機械学習を研究的にやっていますが膨大な時系列データを月・日ごとに切り出して出力したいことがあるかと思います。ただ、そういうやり方をググっても無かったので考えた方法を書いてみることにしました。
流れとしては月の分割も日の分割も同じなので以下では月に限定して書いていきます。

やりたいこと

下のようにいくつかの年月が含まれているデータを月ごと、日ごとに分解してファイルに落とし込みます。
今回扱うのはCSVファイルです。ライブラリはPandasを使います。

完成形

目指す形はこのような感じになります。

使うもの

・Python3.6.5
・Pandas

考え方

ここから本題に移ります。連続しているデータをどやって切り出すのかということですが、いろいろ考えた結果、前後の差分を取り、その値の結果で月が替わるかどうかを判定することにしました。
各データを細かい配列に分解し、その配列をループで読み取っていきます。
現在の配列がi(t)なら、i(t)-i(t-1)で差分を見てやります。例えば6月のデータ同士なら差分が0になるので同月⇒月替りしない、逆に6月と7月なら差分は1になるので月替りということで処理を分岐させます。
ただし、差分をとっただけでは6月の最後尾データに7月の先頭データ(2017/07/01 00:00)が、7月の先頭データは2017/07/01 00:01から入ってしまい時間がずれてしまいますで後述の処理で補正します。

元データの前提条件

ここで言う一月のデータの定義は2017年6月とすると2017/06/01 00:00 ~ 2017/6/30 23:59までです。
(業務の関係上HH:MMとしていますが、原理としてはHH:MM:SSも同じです)
今回使用する元データは最新の状態まで含まれているデータとします。
つまりきれいに1ヶ月入っているわけではなく、月半ばまでのデータが最後となるような
データファイルに対しての処理となっています。また最初の月のデータも途中から始まっていることを条件にします(最初=00:00)から入っていてもいいものとします。

1.データの読み込み

大本となるCSVデータは以下の状態で一つのファイルとしてまとめられています。

ここでは見やすさのためスペース区切りにしましたが、実際はカンマ区切りです。
また、日付は%mm/%ddで書いていますが以下では元のデータ形式のため%m/%dであることに注意してください。

2.配列とデータフレームから数値の抽出

以下でループ処理するために配列を用意します。またファイルから取り出したデータはそのまま使うことができないのでvalueメソッドを使って値を取り出す処理を書きます。

3.ループ処理開始

本当は内包表記などを使いたいのですが今回はプロトタイプの状態で書いてあるので少し汚いコードになります。

last_date, last_dataについて

上記コメントに書いた「後述します」についてです。
今回のような処理の場合、例えば6月と7月のデータには以下のような値が入っています。

これを見ると6月の最後要素は7月の先頭要素に入るべきデータが格納されています。
後者に対してはデータフレーム化時にsep_date[:1]とすることで取り除くことができます。
一方、前者については別の方法を考える必要があります。
そこで一月のループ処理が終わった時点でdate配列およびdata配列の最終要素を別の配列last_date,laste_dataに格納し、last_の要素を次のループ時に先頭要素に追加することで補正することができます。
例:
今、6月でループを回しているとします。すると上記のように6月に入るデータは

です。6月は00:01から始まるのでここでは先頭要素に対して処理はしません。
最後要素の2017-07-01 00:00はsep_date[:-1]で6月配列からは除去します。
また同時にlast_date,last_dataに2017-07-01 00:00とこのときのデータを格納します。
すると次の7月のループではすべての要素を格納し終わった段階(2017-08-01 00:00も除去済み)で、

が効いてくるので、この7月配列の先頭に2017-07-01 00:00が入り結果的に7月配列は[2017-07-01 00:00 ~ 2017-07-31 23:59]を得ます。

少し複雑になってしまいましたが、本当はもっと簡単で良い処理があるかもしれません。
ただ、これによって作業が捗ったのは事実です。

この記事を書いた人

アバター

グローディア 株式会社

グローディア株式会社アカウントです。