日付データ(%Y/%m/%d)を含むExcelから条件を満たす行を抜き出す

  • 6
    いいね
  • 0
    コメント

概要

・pd.to_datetimeは便利。
・pd.read_csvするとき、文字コードは気にする必要がある。
・seaborn良いかも。

使うデータについて

Excelファイル
・日付データを含む
・いろんな列がある
・1行目は無駄なデータがはいっている
○○,○○,2016/8/11,○○,○○
みたいなデータ。日付の要素名は、仮に「期限」とする。データについて、もう少し詳細に書くと、

...,件名(文字列),...,期限(%Y/%m/%d),...,

データの読み込み(pands)

これをまずはcsvファイルとしてpandasから読み込む準備として、csv形式で、Excelからエクスポートした。
次にDataFrameとしての読込。

data = pd.read_csv('./ファイル.csv', encording='Shift-jis', skiprows=1)

encording='Shift-jis'するまでに少し時間がかかった。
Python3なら、特に文字コード気にしなくてもエラー出ないという勝手なイメージがあったがそんなこともなかったです。

目的箇所の抜き出し

今回は、日付部分が未来になっているところを抜き出すとする。
そこで、日付部分のデータ抜き出しと、今日の日付との比較を行い、フィルタとして保持する。

myfilter = pd.to_datetime(data['期限']. format='%Y/%m/%d', error='coerce' > datetime.datetime.today()

ここらへんはもう改変余裕で、期限を過ぎているところを抜き出したければ、

myfilter = pd.to_datetime(data['期限']. format='%Y/%m/%d', error='coerce' < datetime.datetime.today()

pd.to_datetimeに行き着くのに時間がすこしかかった。とても便利な日付操作のメソッドがpandasには用意されているのですね。
http://sinhrks.hatenablog.com/entry/2014/11/09/183603
を参考にしました。

error='coerce'もすこしひっかかりました。日付データに日付を入力せず、記号を入力している行があり、これがエラーの原因になっていました。今回は、エラーをNaTにすることにしました。他に2種類の方法があります。
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.to_datetime.html
を参考にしてください。

その他のパターン(日数計算)

設定された期限から今日までに、どれくらいの日数が経過したかを知りたければ、datetimeどおしの引き算をすればよい。例えば、

days = datetime.datetime.today() - pd.to_datetime(data['期限'], format=%Y/%m/%d, errors='coerce')

これをplotしたい場合には、そのままでは出力できない(数値データじゃない、といわれる)ので、例えば、

days = days / np.timedelta64(1, 'D')

とわり算をして、float型にする必要がある。ここに至るまでもまあまあ時間がかかった。

その他のフィルタ作成パターン(NaTの箇所を抜き出す)

pd.to_datetime()するときに、、errors='coerce'にすると、エラーはNaTになりますが、これがNaTのところを抜き出す、例えば、日付データが未記入のデータを抽出したいような場合には、

filter = pd.to_datetime(...).isnull()

です。NaTはisnull()です。これもちょっと検索して見つけるのに時間かかりました。

出力用データの作成

あとは、フィルタをつかって出力するだけですが、特定の情報(列)だけ出力すればよかったので、

print(data[myfilter]['特定の列の名前'])

としました。後は適当に変更すれば、ファイルとして出力もできるので、おっきなExcelファイルから特定のデータ(行)を抜き出して、あと期限まで何日か、を可視化したりしようと思います。

グラフ化

pandasのDataFrameのデータは、seabornでグラフ化するのがよさそう。
件名を縦軸に、横軸を日数にした棒グラフにしたければ、

sns.barplot(x='日数', y='件名',data=data)

という感じ。グラフに利用したい列名を、xとyで指定すれば、seabornが勝手にうまくまとめてくれる。

参考は、https://stanford.edu/~mwaskom/software/seaborn/examples/horizontal_boxplot.html
です。

seaborn(matplotlib)のグラフ位置を微調整したい場合には、
plt.subplot_adjust(left=*, right=*, top=*, bottom=*)を利用します。
これは、実際にグラフを表示して微調整すると感覚つかめますが、グラフの見える領域のいちばん右端を1.0としたときの、グラフの左端の位置と右端の位置のようです。
だから、right=1.0より大にすると見える領域からグラフがはみ出ます。例えば、left=0.5, right=1.0とすると、半分がグラフ領域になり、左がたくさん空いたグラフになります。そして、必ず、left<rightです。topとbottomの関係も似たようなものです。

グラフで日本語フォントを使いたい場合

fp = FontProperties(fname='C:\Windows\Fonts\YUGOTHL.TTC`. size=10)

とかして、

plt.xtics(fontproperties=fp)
plt.ytics(fontproperties=fp)

とかすれば、x軸でもy軸でも日本語が文字化けしません。使うフォントはお好みで。エクスプローラで調べれば出てきます。ただ、フォント閲覧用のGUIになるので、パスを見るのがちょっと手間かも。

ラベルで日本語使いたい場合には、

plt.ylabel('ラベル', fontproperties=fp)

です。

グラフの表示もしくは、保存

plotしたグラフの表示は、

plt.show()

保存したい場合には、

plt.savefig('ファイル名')

ファイル保存するときには、plt.savefig('ファイル名', dpi=300)のような解像度の指定もできる。
ファイル名に日付を利用したい場合は例えば、

today = datetime.datetime.now()
plt.savefig("ファイル名_{}-{}-{}.png".format(today.year, today.month, today.day))

などとする方法がある(例:ファイル名_2016-08-14.png)。もっとスマートな方法もある気がするけど、いまの自分にはこれしかわからない。けど、format関数便利ですよね。