LoginSignup
7
8

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-08-11

概要

・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関数便利ですよね。

7
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
8