POSTD PRODUCED BY NIJIBOX

POSTD PRODUCED BY NIJIBOX

ニジボックスが運営する
エンジニアに向けた
キュレーションメディア

Robin Wilson

本記事は、原著者の許諾のもとに翻訳・掲載しております。

ここ1年、私はPythonに関するブログをたくさん書いてきました。そこで今回は、2015年における、私にとって”新しい”Pythonモジュールの中から、お気に入りものを厳選してご紹介したいと思います。なお、以下に挙げるモジュールは、必ずしも2015年に新規にリリースされたものではありません。ただ、”私にとっては目新しい”ものだったので、恐らく皆さんも新鮮に感じるのではないかと思います。

tqdm

tqdmはとても シンプル であり、かつ非常に 実用的 なモジュールです。これを使えば、コード内に含まれるループの進捗バーを、驚くほど簡単に表示できます。例えば以下のようなコードがあったとしましょう。

for item in items:
    process(item)

このiterableを単純にtqdm関数でラップします。

from tqdm import tqdm

for item in tqdm(items):
    process(item)

すると以下のような美しい進捗バーが表示されます。

18%|█████████                               | 9/50 [00:09<;00:41,  1.00it/s

最近、このモジュールを妻に紹介したところ、そのシンプルさと実用性に驚いていました。

joblib

joblibの存在は以前から知ってはいたものの、実際のところはよく理解しておらず、いろいろな機能を寄せ集めたようなモジュールだと思っていました。まあ、その印象は今もあまり変わりませんが、実は非常に便利なモジュールだったのです。私は Flowminder の同僚から再度joblibを勧められて、このモジュールをデータ分析用のコードに幅広く使用しました。では、その機能について紹介しましょう。joblibは大きく分けて、 キャッシング並列化永続化 (データの保存と読み込み)の3つの機能から成ります。実を言うと、私はまだ並列プログラミングの機能は使ったことがないのですが、あとの2つの機能は頻繁に使ってきました。

キャッシング機能とは、シンプルなデコレータを使って、関数を簡単に”メモ化”する機能です。具体的には、関数の計算結果をキャッシュしておき、再度同じパラメータを使ってその関数が呼び出された際に、結果をキャッシュから読み出すことで処理時間を短縮します。なお、キャッシング機能を使う際は、メモ化する関数の引数を慎重に選ぶようにしましょう。joblibでは超高速のハッシュ関数を使用して引数を比較しますが、何ギガバイトもある巨大な配列を処理するとなると、さすがに時間がかかってしまいます。そのような場合は、ファイル名、日付、モデルのパラメータなど、巨大な配列の作成に使用される値を引数に取る関数をメモ化するのが良いでしょう。そうすることで、巨大な配列を読み込んだり、関数が呼び出されるたびにその配列のハッシュ値を計算したりする処理が省けます。

上記のメモ化の機能と密接に関連しているのが永続化の機能で、これはキャッシュされた結果をファイルに保存するのに使われます。基本的な機能はビルトインの pickle モジュール(または後述の dill モジュール)と同じですが、NumPy配列を含むオブジェクトに対しては非常に効果的に機能します。インターフェースはpickleと全く同じ(シンプルな load 関数と dump 関数)なので、切り替えが非常に簡単です。私は途中で気が付いたのですが、 compressed=True と設定すると、出力ファイルが明らかに小さくなり、出力結果が1ファイルに集約されます( .pkl ファイルや大量の .npy ファイルが生成されるデフォルトの動作とは正反対です)。

folium

folium
私はfoliumを、かろうじてざっとかじっただけですが、このライブラリはPythonからの地理的データを即席で描きだすのに、 実に 役に立ちます。おまけにJupyter Notebookとでさえうまく動作します。

このドキュメンテーション からのコード例の一部を見ても、どれほど簡単に使用できるかが分かります。

map_1 = folium.Map(location=[45.372, -121.6972])
map_1.simple_marker([45.3288, -121.6625], popup='Mt. Hood Meadows')
map_1.simple_marker([45.3311, -121.7113], popup='Timberline Lodge')
map_1.create_map(path='output.html')

使用されているバックグラウンドマップ(あらゆるリーフレットのタイルセットも機能します)、ポイントアイコン、カラー、サイズ、その他多くの要素を含めて、上記のマップのほぼ全ての面を、容易に構成することができます。GeoJSONデータを視覚化し、コロプレスマップも作成することができます(さらにPandasのデータフレームともリンクしています)。

このモジュールもまた、Flowminderとの仕事で使用しました。後になっていろいろな他のコンテキストでも使ってみました。上記のコードを用い、ループで simple_marker に呼び出しを行うことで、たくさんのポイントを簡単に視覚化できます。

また上の例は、指定されたHTMLファイルへマップを保存する方法を表しています。しかしJupyter Notebookの中での使用は、Mapオブジェクト(上の例で言うと map_1 )がそれ自体でセルの最終ラインにあることを確かめるだけです。Jupyter Notebookは魔力を働かせ、それをインラインに示します。完璧ですね。

tinydb

私にとって”新しい”モジュールのrecipyの最初のバージョン(Collaborations Workshop 2015 (CW15)で発表したもの)では、バックエンドデータの保存用にMongoDBを使用しました。しかし、最初にMongoDBサーバをインストールし、動作させる必要があったので、インストール/セットアップの手順がかなり複雑になりました。私がpure-Python NoSQLデータベースを探している時に、TinyDBに出会いました。これには単純なインターフェースがあって、ここまで投げかけてきたもの全てに対応していました。

より長期的には recipy のためのバックエンドを可変にすることについて考えています。MongoDBの利点(ネットワークを介して簡単に、より優れたパフォーマンスのデータベースを共有できる)を活用したい、とユーザが思っている場合でも、私たちの生活をもっと楽にしてくれるTinyDBをデフォルトのDBとして使い続けるでしょう。

dill

dill は、より優れた pickle (納得できますか? )です。あなたはディスクにさまざまなPythonオブジェクトを保存するために、おそらくビルトイン pickle モジュールを使用してきたでしょう。ですが、時々、このようにエラーが出たかもしれません。

PicklingError                             Traceback (most recent call last)
<ipython-input-5-aa42e6ee18b1> in <module>()
----> 1 pickle.dumps(x)

PicklingError: Can't pickle <function <lambda> at 0x103671e18>: attribute lookup <lambda> on __main__ failed
 attribute lookup <lambda> on __main__ failed

こうなってしまうのは、pickleオブジェクトがpickle化できるものの中で比較的、制限されているからです。つまり入れ子関数やlambda、スライスや、その他いろいろなものを処理できません。これらのオブジェクトを直接pickle化したいケースは、それほどはないかもしれませんが、pickle化したい他の物の 中に 、そういったオブジェクトが出てくることは、かなり一般的です。そのため、pickle化が失敗する原因となるのです。

より多くのものをpickle化できるようになることで、 dill は、この問題を解決します。実際のところ、フレームやジェネレータやトレースバックとは関係なく、ほとんどあらゆるものをpickle化できます。先にご紹介したjoblibと同様、インターフェースは pickle と全く同じ( loaddump )なので、切り替えは実に簡単です。

また、 RData ファイルにセッション全体を保存できるRの性能が気に入っている方にお勧めしたいのは、dillには dump_session および load_session 関数もあるということです。これは、まさに待ち望んでいたものです。

おまけ: Anaconda

これは”おまけ”であって、実質的にはPythonのモジュールではありません。でも、私は2015年に使い始めて(そうです、私は乗り遅れたのです)、今ではこれが無いと困るほどです。

Anacondaにはちょっと分かりにくいところがあります。というのも、Anacondaは複数のパーツから構成されているからです。それらの集合体が”Anaconda”と呼ばれるものです。そのパーツとは、以下のようなものです。

  • Scientific Pythonディストリビューションのクロスプラットフォームであり、 Enthought Python Distribution や、 WinPython などと同じラインです。一度 ダウンロード してインストールすれば、標準ライブラリ(NumPy, SciPy, Pandas, matplotlib, sklearn, skimage、その他いろいろ)を含む、フルスタックのScientific Pythonを入手できます。ユーザには全部で4つの選択が用意されています。Python 2またはPython 3を選べて、どちらにも、フルサイズのAnacondaのディストリビューションか、縮小版のMinicondaのディストリビューションがオプションで付いています。これによって以下のことが可能になります。
  • condaパッケージのマネージメントシステムは、Pythonのパッケージとともに稼動するようにデザインされていますが、 あらゆる バイナリをインストールする際に使えます。それならpipによく似ていると思うかもしれませんが、pipよりもずっと優れているのです。というのも、(a)バイナリをインストールします(ソースからnumpyをコンパイルする必要はありません! )。(b)pipよりも依存関係の扱いに優れています。(c)異なるパッケージをインストールし、 かつ 、異なるPythonのバージョンを稼働することができるような、複数の 環境 を容易に作り出すことができます。
  • anaconda.org のリポジトリ(以前はbinstarと呼ばれていました)では、アカウントを作成してバイナリのcondaパッケージをアップロードし、他の人と簡単にシェアできます。例えば、私はそこで提供されていた2つのcondaパッケージを入手しましたが、それを使えば、condaを使っている人なら誰でも簡単にインストールできます。

さあ、以上が 私にとって新しい 、2015年のPythonモジュールトップ5です。便利だと感じてもらえると嬉しいです。皆さん、楽しいクリスマスと新年をお過ごしください。

(この記事が気に入った方は、 Jupyter Notebook extensionsの簡単なインストール方法Bokeh plotsとデータフレーム基盤のツールチップPytohnにおける直交距離回帰 もぜひご覧になってください。)