ここではWebのアクセスログとしてApacheの標準フォーマットを例にデータを分析できるように構造化していく方法を説明します。
まずデータの準備ですが、Apacheのオンラインマニュアルの「ログファイル」(リンク)にある「Common Log Format」のサンプルを使いたいと思います。
同じデータを5行コピー(1行でもよいですが)して、「apache_log.txt」というファイル名で保存しておきます。
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
データの整形やテキストの抽出には正規表現モジュール(re)を用います。Pythonに標準で付属する正規表現モジュールをインポートし(In [1])、ログファイルを読み取りようにオープンします。
ファイルのデータを1行ずつ読み込んで(In [5])正規表現のsub関数を使ってログを8つのパートに分割し、書き込み用のファイル(In [3])にCSV形式で書き込みます。
In [1]: import re In [2]: fr = open('apache_log.txt') In [3]: fw = open('formated.csv', 'w') In [4]: line = fr.readline() In [5]: while line: ...: fline = re.sub(r'^(\S+) (\S+) (\S+) \[([^\]]+)\] "([A-Z]+) ([^ "]+)? HTTP/[0-9.]+" ([0-9]{3}) ([0-9]+|-)', r'\1,\2,\3,\4,\5,\6,\7,\8', line) ...: fw.write(fline) ...: line = fr.readline() ...: In [6]: fr.close() In [7]: fw.close()
CSV形式のデータができてしまえば、いつものようにread_csv関数でDataFrameに読み込んで処理することが可能になります。ここでは先に8つのパートに分割したデータを表のように項目名を付けて読み込んでいます(In [2])。
項目名 | 説明 |
---|---|
ip | サーバへリクエストをしたクライアント(リモートホスト)の IP アドレス |
identd | クライアントのマシンのidentdにより決まRFC 1413のクライアントの アイデンティティ |
user | HTTP 認証による、ドキュメントをリクエストした人のユーザーID |
datetime | サーバがリクエストを受け取った時刻 |
method | クライアントが使ったメソッド |
request | クライアントから要求されたリソース |
status | サーバがクライアントに送り返すステータスコード |
size | クライアントに送信されたオブジェクトの、応答ヘッダを除いたサイズ |
4列目の日付と時刻のデータはタイムゾーン(-07:00)が指定されていて、日本標準時(+09:00)ではないのでタイムゾーンを変換します。(In [3]〜In [5])これで日本標準時に基づいた日付と時刻を持つデータセットが完成です。
In [1]: import pandas as pd In [2]: df = pd.read_csv('formated.csv', header=None, names=['ip', 'identd', 'user', 'datetime', 'method', 'request', 'status', 'size']) In [3]: df.index = pd.to_datetime(df['datetime'], format='%d/%b/%Y:%H:%M:%S -0700') In [4]: df = df.tz_localize('US/Arizona') In [5]: df = df.tz_convert('Asia/Tokyo') In [6]: df['ip'] Out[6]: datetime 2000-10-11 05:55:36+09:00 127.0.0.1 2000-10-11 05:55:36+09:00 127.0.0.1 2000-10-11 05:55:36+09:00 127.0.0.1 2000-10-11 05:55:36+09:00 127.0.0.1 2000-10-11 05:55:36+09:00 127.0.0.1 Name: ip, dtype: object
続いて、XML形式のデータをDataFrameに取り込んで分析できる状態にしてみましょう。XMLを取り扱う時には、XMLモジュール(xml)を利用します。サンプルデータとして@ITのRSS(http://rss.rssad.jp/rss/itmatmarkit/rss.xml)データを使用します。
前回もご紹介したurllib2モジュールを使ってRSSデータを取り込みtreeに格納します。ここではタイトル(title)と公開時刻(pubDate)を取り出して2列のデータセットをもつDataFrameを生成しています。
In [1]: import pandas as pd In [2]: from xml.etree import ElementTree In [3]: import urllib2 In [4]: link = 'http://rss.rssad.jp/rss/itmatmarkit/rss.xml' In [5]: socket = urllib2.urlopen(link) In [6]: tree = ElementTree.parse(socket) In [7]: title = tree.findall(".//item/title") In [8]: titlelist = [i.text for i in title] In [9]: pubdate = tree.findall(".//item/pubDate") In [10]: pubdatelist = [i.text for i in pubdate] In [11]: index = range(len(pubdatelist)) In [12]: df = pd.DataFrame(index=index, columns=('pubdate', 'title')) In [13]: df['pubdate'] = pd.to_datetime(pubdatelist) In [14]: df['title'] = titlelist
今回は「データを分析できる状態にする」をテーマに、ビジネスデータの分析で欠かすことのできない時系列データを中心にデータの取り扱いについて紹介しました。また、正規表現を用いてWebなどのログを分析できるフォーマットに成型する方法も紹介しました。
正規表現は非常にパワフルでこういったデータの整形には必須のツールですが非常の奥が深く難しい面もあるので、これを機に慣れ親しんでください。
次回は、「データ分析の方法についての検討」というテーマで、データが分析できる状態になったら、次はどのような分析手法を用いるかを検討します。まずはデータを視覚化して全体像や傾向を把握し、目的に応じた分析手法を検討します。
Copyright © ITmedia, Inc. All Rights Reserved.