luggage baggage

Machine learning, data analysis, web technologies and things around me.

Pandas メジャーアップデート(0.20.1)の要点〜高速 I/O、集約関数強化など

こんにちは。吉田弁二郎です。

先日(5月5日)、pandas の最新版 0.20.1 がリリースされました。agg/transformメソッドがgroupbyしなくても使えるようになり、10倍以上高速な I/O を実現する feather-format が(試験的に)導入され、スライスの際に頻繁に利用されていた.ixインデクサが deprecated となるなど、全般的に着実な改善もしくは変更がされている印象です。以下、リリースノートのハイライト部分より、目についたものをピックアップしていきます。

agg/transformが Series/DataFrame に対して直接使える

従来はgroupbyメソッドを呼んだ際につくられる SeriesGroupBy/DataFrameGroupBy オブジェクトで利用可能だった集約関数aggおよびtransformが Series/DataFrame オブジェクトから直接呼べるようになりました。例えば、

df = pd.DataFrame({'x': np.random.randn(5), 'y': np.random.randn(5)})
#          x         y
# 0  0.405046 -0.544307
# 1  0.378932  0.845846
# 2  0.463125  2.251753
# 3 -0.586262  1.705797
# 4  0.408864  0.436262

transformed = df.transform(lambda x: (x - x.mean())/x.std())
transformed.describe()
#                  x             y
# count  5.000000e+00  5.000000e+00
# mean  -4.440892e-17 -3.330669e-17
# std    1.000000e+00  1.000000e+00
# 以下省略

という感じで、各列ごとに正規化したりするのに使えて便利ですね。
http://pandas.pydata.org/pandas-docs/stable/whatsnew.html#agg-api-for-dataframe-series

10倍以上の書き込み/4倍以上の読み込み速度を実現する feather-format をサポート

新しいデータフォーマット feather-format が pandas の read/write で処理できるようになりました。実際にどの程度速度差があるのか見てみたいと思います。

テスト用のデータセットとして、映画評価データ IMDB 5000 Movie Dataset | Kaggle を使います。ダウンロードして入手できる csv ファイルのサイズは約 1.4MB ですが、通常業務で向き合うデータサイズから見ると小さすぎるのでかさ増しした状態でやりましょう。

movie = pd.read_csv('movie_metadata.csv')
movie_100x = pd.concat([movie for i in range(100)], ignore_index=True)  # サイズを100倍にかさ増し

まずは書き込みから。

%timeit movie_100x.to_csv("movie_metadata_100x.csv", index=False)
14.4 s ± 257 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit movie_100x.to_feather("movie_metadata_100x.feather")
1.38 s ± 138 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

となり約10倍以上の高速化がされていると分かります。次に読み込みは

%timeit pd.read_csv("movie_metadata_100x.csv")
5.66 s ± 207 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit pd.read_feather("movie_metadata_100x.feather")
1.25 s ± 24.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

と約4倍以上のパフォーマンスが出ています。高速化の倍率はおそらくデータサイズに依存して変わると思いますが、いずれにしても、大きなデータを扱う際には有望なファイル形式が pandas で使えるようになったと言えそうです。ただし、Python 版の feather 開発者である Wes McKinney によると(pandas の考案者・開発者でもある)

Note to users: Feather should be treated as alpha software. In particular, the file format is likely to evolve over the coming year. Do not use Feather for long-term data storage.

ということなので、本番利用は今後の開発を待った方がいいかもしれません。

なお、ファイルサイズは、変換後のmovie_metadata.featherが約 1.9MB と元の 1.4MB からはかなり大きくなっています。
http://pandas.pydata.org/pandas-docs/version/0.20/io.html#feather

.ix インデクサが deprecated に

これは個人的にかなり衝撃を受けた項目です。DataFrame からのデータ抽出に便利に使える.ixインデクサが廃止予定となりました。pandas 0.20.1 では警告が出るのみで利用自体は可能だというものの、将来的には不可能になります。代わりに.locもしくは.ilocを使うことで、検索対象が「ラベル」なのか「位置(数値)」なのか表現を厳密にする必要があります。
http://pandas.pydata.org/pandas-docs/version/0.20/whatsnew.html#deprecate-ix

インデックスに対してもgroupbyできる

groupby関数のby引数として、インデックスを指定できるようになりました(これまでは KeyError が出ていた)。

df = pd.DataFrame({'x': np.random.randn(5), 'y': np.random.randn(5)}, index=list('aabbc'))
df.index.name = 'idx'
#             x         y
# idx
# a   -1.527253  0.735587
# a   -0.336519 -0.757381
# b   -0.142629 -1.385499
# b   -0.220486 -0.306491
# c   -1.858252  1.056412

df.groupby('idx').sum()
#             x         y
# idx
# a   -1.863772 -0.021794
# b   -0.363115 -1.691990
# c   -1.858252  1.056412

pivot_tableあたりを使って階層的インデックスづけされた DataFrame を得た後、インデックスに関して集約関数をかませたい時とかに使えそうです。
http://pandas.pydata.org/pandas-docs/version/0.20/whatsnew.html#groupby-enhancements

エクセル出力時にスタイルを変更できる

こちらは下記リンクを見ていただくのが一番わかり易いかと思います。DataFrame をto_excel経由でエクセル形式で出力する際、セルや文字の色付け、フォーマッティングなどのスタイリング処理が CSS2.2 ベースでできます。データ分析結果をプランナー等に渡す際、どうしてもエクセルで見やすくする必要があるといった状況で有用な感じです。
http://pandas.pydata.org/pandas-docs/stable/whatsnew.html#excel-output-for-styled-dataframes

動作確認環境

OSX: 10.11.6
Python: 3.6.1
IPython: 6.0.0
Numpy: 0.12.1
Pandas: 0.20.1