256

私は定期的に 1,500 万行を超えるデータ フレームに対して pandas 操作を実行しており、特定の操作の進行状況インジケーターにアクセスしたいと考えています。

pandas split-apply-combine 操作のテキストベースの進行状況インジケーターは存在しますか?

たとえば、次のようなものです。

df_users.groupby(['userID', 'requestDate']).apply(feature_rollup)

wherefeature_rollupは、多くの DF 列を取り、さまざまな方法で新しいユーザー列を作成するやや複雑な関数です。大きなデータ フレームの場合、これらの操作には時間がかかることがあるため、進行状況を更新する iPython ノートブックでテキスト ベースの出力が可能かどうかを知りたいです。

これまでのところ、Python の正規ループ進行状況インジケーターを試してみましたが、意味のある方法で pandas とやり取りすることはありません。

分割-適用-結合の進行状況を知ることができる pandas ライブラリ/ドキュメントで見落としているものがあることを願っています。apply単純な実装では、関数が動作しているデータ フレーム サブセットの総数を確認し、進行状況をそれらのサブセットの完了した部分として報告します。

これはおそらくライブラリに追加する必要があるものですか?

4

9 に答える 9

19

ジェフの答えを微調整する(そしてこれを再利用可能な関数にする)。

def logged_apply(g, func, *args, **kwargs):
    step_percentage = 100. / len(g)
    import sys
    sys.stdout.write('apply progress:   0%')
    sys.stdout.flush()

    def logging_decorator(func):
        def wrapper(*args, **kwargs):
            progress = wrapper.count * step_percentage
            sys.stdout.write('\033[D \033[D' * 4 + format(progress, '3.0f') + '%')
            sys.stdout.flush()
            wrapper.count += 1
            return func(*args, **kwargs)
        wrapper.count = 0
        return wrapper

    logged_func = logging_decorator(func)
    res = g.apply(logged_func, *args, **kwargs)
    sys.stdout.write('\033[D \033[D' * 4 + format(100., '3.0f') + '%' + '\n')
    sys.stdout.flush()
    return res

注: 適用の進行状況のパーセンテージはinline で更新されます。関数が標準出力の場合、これは機能しません。

In [11]: g = df_users.groupby(['userID', 'requestDate'])

In [12]: f = feature_rollup

In [13]: logged_apply(g, f)
apply progress: 100%
Out[13]: 
...

通常どおり、これをメソッドとして groupby オブジェクトに追加できます。

from pandas.core.groupby import DataFrameGroupBy
DataFrameGroupBy.logged_apply = logged_apply

In [21]: g.logged_apply(f)
apply progress: 100%
Out[21]: 
...

コメントで述べたように、これはコア パンダが実装に関心を持つ機能ではありません。しかし、Python を使用すると、多くの pandas オブジェクト/メソッドに対してこれらを作成できます (これを行うのはかなりの作業になります... ただし、このアプローチを一般化できるはずです)。

于 2013-09-04T10:37:32.340 に答える
5

これはデコレータで簡単に行うことができます

from functools import wraps 

def logging_decorator(func):

    @wraps
    def wrapper(*args, **kwargs):
        wrapper.count += 1
        print "The function I modify has been called {0} times(s).".format(
              wrapper.count)
        func(*args, **kwargs)
    wrapper.count = 0
    return wrapper

modified_function = logging_decorator(feature_rollup)

次に、 modified_function を使用します(印刷したいときに変更します)

于 2013-09-04T00:26:42.867 に答える