区切り文字の数が変だったり、日付がおかしい(19950000みたいなの)場合はpandasの場合は容赦なくコケる(しかもエラー内容がわからなかったりする)。
Rの場合しれっとスキップするのでさくさく感はあるのだけど、どのデータ落としたのか注意していないとわからないので、自分の場合はまずは綺麗なデータにするということをきちっとやるほうが、自分でデータをネグったという認識ができて後々悩まなくてよいかなと思っている。
実行結果。pandasのmulti indexは便利ですね。
In [2]: execfile("ml1.py") In [3]: d.head() Out[3]: DateOccurred DateReported Location YEAR MONTH Location YEAR MONTH AB 2004 3 1 1 1 1 1 2005 4 1 1 1 1 1 2010 7 1 1 1 1 1 AK 1990 1 1 1 1 1 1 3 1 1 1 1 1
この先がよくわからないんだけどdate_rangeかなんかで月ごとのSeriesを作ってからjoinすればいいのかなぁ。
コード。最初に汚い行(tabの数がおかしい、日付の表現が変)というデータを捨ててpandasに読み込めるようにしてからpandasで処理しています。
import pandas as pd from datetime import datetime from numpy import nan import re re_date = re.compile("\d{4}[01]\d[0123]\d") with open("ufo.tsv", "w") as w: with open("ufo_awesome.tsv") as f: for l in f: s = l.split("\t") if len(s) == 6: if re_date.match(s[0]) and re_date.match(s[1]): if int(s[0][4:6]) > 0 and int(s[0][6:8]) > 0: w.write(l) def get_loc_code(loc): l = loc.split() if len(l) == 2 and len(l[1]) == 2: return l[1].upper() else: return nan d = pd.read_table("ufo.tsv", header=None, names=["DateOccurred", "DateReported", "Location", "ShortDescription", "Duration", "LongDescription" ], parse_dates=["DateOccurred", "DateReported"], date_parser=lambda x: datetime.strptime(x, '%Y%m%d') ) d = d.drop(["LongDescription", "ShortDescription", "Duration"], axis=1) d.Location = d.Location.apply(get_loc_code) d = d.dropna() d = d[d.DateOccurred > datetime(1990, 01, 01)] d["YEAR"] = d.DateOccurred.apply(lambda x: x.year) d["MONTH"] = d.DateOccurred.apply(lambda x: x.month) d = d.groupby(["Location", "YEAR", "MONTH"]).count()