データを分析のために整形する
データの下準備・計算・可視化については実際のところ、人々の注目や関心がだいたい 1:4:5 くらいなのに対し、実務における比率はといえば 6:2:2 くらいなのが現実かと思います。これはあくまで体感ですが、分析のほとんどはデータを計算可能な状態にお膳立てするための下準備と言っても差し支えないのでしょうか。そんなわけで今日は日頃グルー言語としての使い勝手を強調している Python でよく使うテクニックを書き連ねてみます。
JSON オブジェクトのロードとアンロード
内容に特に真新しさは無いのですが JSON フォーマットの変換は事前処理としてよくやることです。忘れないようにメモ代わりに残します。
Python では JSON 形式のデータ構造は import json することで扱えるようになります。ロード時は辞書 (他の言語で言うハッシュ) 型のデータ形式となり、これをまた JSON 形式にすることもできます。
CSV ファイルからの JSON データのロード
キー、値で区切られた CSV ファイルを想定します。値の部分には他のシステムでシリアライズされた JSON 形式のテキストデータが格納されているとします。これを読み込むには次のようにデリミタを指定して文字列を分割、 json.load メソッドで JSON を辞書型のオブジェクトとしてロードできます。
import json
file = open(self.filename, 'r')
for line in file:
key, value = line.rstrip().split(",")
dic = json.loads(value)
JSON オブジェクトをファイルに書き出す
反対に辞書型のオブジェクトを JSON 形式でファイルや標準出力に書き出すときは次のように json.dumps を利用します。
import json
json_obj = json.dumps(dic)
print(json_obj)
簡単ですね。
引数とインスタンス変数の利用
Python スクリプトに渡した引数は sys.argv に格納されます。
import sys
if __name__ == '__main__':
argsmin = 1
if len(sys.argv) > argsmin:
some_instance = SomeClass(sys.argv)
some_instance.some_method()
インスタンスの初期化時に渡しておけば、インスタンス変数に引数を格納して利用できます。
class SomeClass:
def __init__(self, args):
self.filename = args[1]
プライベートメソッド
Python では習慣的にメソッドの頭に _ をひとつ付けることによってプライベートメソッドであるとします。
def self._some_method(self):
...
確かにこれなら some_instance.some_method として呼ぶことはできません。しかし実は明示的に some_instance._some_method とすれば呼ぶことができます。習慣的なものであって機能的にプライベートになっているわけではありません。
機能的に呼ばれないようにするには __ をふたつにします。
def self.__some_method(self):
...
ただしこれでも裏技的に呼び出す方法がある上、プライベートメソッドのテスタビリティが下がることになるのであまりオススメしません。プライベートメソッドを呼び出すことができてしまうのは、言い換えればテストの時は逆にラクをできることになります。
テスティングフレームワーク
Python のテスティングフレームワークは様々なものがありますが nose が比較的使いやすいです。まずは以下のような動作をするメソッドを考えてみます。
import factorial
factorial.factorial(10)
#=> 3628800
テスト対象のコード
この Python コードは factorial.py という名前であるとし、メソッドの実装はこのような感じとします。
def factorial(n):
if n==1:
return 1
else:
return n * factorial(n-1)
テストコード
これをテストするには test_factorial.py という名前のファイルを作成しテストコードを以下のように記述します。
from nose.tools import * # テスティングフレームワークの読み込み
from factorial import * # テスト対象のコードの読み込み
def test_factorial(): # factorial メソッドのテスト
i=10
e=3628800
eq_(e,factorial(i)) # 検証
上記は eq_(3628800 ,factorial(10)) をしているのと等価です eq_ メソッドで値が等しいかを検証しています。
テストの実行
テストコードが実装できたらシェルから nosetests コマンドを発行します。
$ nosetests
.
----------------------------------------------------------------------
Ran 1 test in 0.008s
OK
まとめ
地道なデータの準備作業にたくさんの時間を費やすことはありがちです。今回はそんな作業でよく使うテクニックについて備忘録的にまとめました。