Edited at

Pythonの数値計算プロジェクトを新規作成する

More than 1 year has passed since last update.

この記事は株式会社ネクスト(Lifull) Advent Calendar 2016の18日目です。

こんにちは、デジタルマーケティングUの二宮です。

最近、社内のいくつかの部署で、統計処理や数値計算にPythonを使うプロジェクトが誕生しています。

これまでは同じグループの @wakuteka さんを中心としてR言語を利用しており、ドキュメントやノウハウもそれなりにまとまっていたのですが、



  • R言語はファンキーな仕様が多く、
    引き継ぎや外部とのやり取りがつらい

  • 汎用的な言語としても (例えばWeb開発言語) 使いたい

  • 使えるライブラリが異なるので選択肢を広く持ちたい

というニーズもあったようです。

(もちろんR言語を貶めているのではなく、tidyverseと呼ばれるライブラリ群を用いたインタラクティブな分析・可視化の用途はR言語のほうが使い勝手が良いです。道具は使い所ってことですね。)

私は趣味でPythonを使っており、レビューやアドバイス(というと大げさなのですが)の形で、いくつかのプロジェクトにも関わる機会がありました。

その中で得られた知見や、参考にしていった記事などをまとめていこうと思います。

ただし、試行錯誤しながら進めていったため、もっといい方法があるかもしれませんし、記事の内容も開発全体を網羅しているわけではありません。もしそういう点を見つけた場合は、コメント等で教えて頂けるとうれしいです。


Pythonの環境を用意する

Pythonをまじめに書こうと思って作った開発環境」という記事が参考になりました。

統計用ライブラリも抱え込んだAnacondaというPythonディストリビューションが有名ですが、本番環境では使っていません。

(開発・分析環境では使っています。)

それは「pyenvが必要かどうかフローチャート」という記事にもある通り、


Anacondaの/binをパスに設定するのですが、Anacondaがなかで持っているツール(openssl/curl/python)がOSの持っているツールを覆い隠してしまいます。

あと、BASH前提になりすぎてて、zsh使ってると色々直さないと動きません。


実運用上で、この辺の挙動が不安だったからです。


開発

レビューする必要があったので、コーディング規約やDocStringsの書き方などを勉強しなおしました。


(必要に応じて)パッケージとして切り出す

部署独自の数値計算などは、グループ用のgitリポジトリを使って、pipを用いてインストールできるようにしました。

その際、これらの記事を参考にしました。


コーディング規約

PEP8Google Python Style Guideが参考になると思います。

ただし、コーディング規約を目見でチェックするのも手で直すのもつらいので、flake8autopep8も適宜使っています。ただし、PEP8は割と厳しめのコーディング規約なので、適宜相談しながら進めています。

ここでは以下の記事を参考にしました。


DocStringsの記述

また、関数やメソッドの入出力をわかりやすくするため、GoogleスタイルのDocStringsも書いてもらっています。

他にもNumpyスタイル等もあるようです。

Python3.5以降で型アノテーションを利用する場合はこう、

def function_with_pep484_type_annotations(param1: int, param2: str) -> bool:

"""Example function with PEP 484 type annotations.

Args:
param1: The first parameter.
param2: The second parameter.

Returns:
The return value. True for success, False otherwise.

"""

型アノテーションを利用しない場合はこうです。

def function_with_types_in_docstring(param1, param2):

"""Example function with types documented in the docstring.

Args:
param1 (int): The first parameter.
param2 (str): The second parameter.

Returns:
bool: The return value. True for success, False otherwise.

"""

ただし、レビューしたコードの中にtupleで多値を返す関数があったのですが、(自分が調べた範囲では)GoogleスタイルのDocStringsはReturnsで多値を返す書き方に対応していないようでした。

こちらのstack overflowの回答を元に以下のように記述してもらいました。

import pandas as pd

def _postprocess_data(output_data, market):
"""アラート用、ファイル出力用のデータに成形する

Args:
output_data (pd.DataFrame): 計算後のデータフレーム
market (str): 不動産マーケット名

Returns:
tuple: 以下の値を多値で返す
- output_data (pd.DataFrame): アウトプットのデータ
- monthly_data (pd.DataFrame): 月次データ

"""

型アノテーションとmypyを使った静的解析はまだ試していませんが、機会を作って試してみようと思います。


テストコードの記述

小さなプロジェクトだったので、unittestで簡単なテストをいくつか書いてある程度です。

unittest以外にもいくつかのフレームワークがあるらしいのでこれも機会を作ろうと思います。

今は「jupyter notebookで試行錯誤した関数を、エディターに貼り付ける」みたいな感じで進めています。

必要に応じてTDD(的なもの)と使い分けられるようにしたいです。


pandasのデータフレームについて

Pythonでデータ分析を行う際には、pandasを使ってR言語のようなデータフレーム型を導入することになると思います。

R言語ではdplyrやtidyrなどのライブラリで、データの処理の流れをパイプライン演算子を使って簡潔に表現することができるのですが、pandasで同じように行うには少々慣れが必要そうです。

(また、なんでもデータフレームで表現するRと違って、辞書型との使い分けも試行錯誤しています。)

ただし、こちらの記事にpandasのイケてる書き方がまとまっていたので、これから使い始める方はぜひ読んでください。


まとめ

データ分析ライブラリを使ったPythonプロジェクトで試行錯誤した(またはしている最中の)結果を簡単にまとめました。これを読んでいるどなたかのお役に立てればと思います。

記事の内容も開発全体を網羅しているわけではありません。もしそういう点を見つけた場合は、コメント等で教えて頂けるとうれしいです。

また、弊社のAdventCalendarも、引き続きご注目いただければと思います。