pandas.DataFrame.isinを並行して実行する簡単な方法はありますか?


25

DataFrame.isinパンダの機能を多用するモデリングおよびスコアリングプログラムを使用して、数千の特定のページごとに個々のユーザーのFacebookの「いいね」のレコードのリストを検索します。これは、1つのコアでのみ実行され、残りは数十個のコアで同時に実行されるため、モデリングやスコアリングの部分よりも、プログラムの最も時間のかかる部分です。

私は手動でデータフレームをチャンクに分割し、操作を並行して実行できることを知っていますが、それを自動的に行う簡単な方法はありますか?言い換えれば、簡単に委任された操作を実行していることを認識し、それを自動的に配布するパッケージがありますか?おそらくそれはあまりにも多くを求めていますが、私は過去にPythonですでに利用可能なものに十分驚いていましたので、尋ねる価値があると思います。

これがどのように達成されるかについてのその他の提案(魔法のユニコーンパッケージによってでなくても!)も歓迎します。主に、ソリューションのコーディングに同量の時間を費やすことなく、実行ごとに15〜20分間削る方法を見つけようとしています。


値のリストはどれくらいの大きさですか?セットとして渡そうとしましたか?並列処理については、Joblibに興味があるかもしれません。使いやすく、計算を高速化できます。大量のデータで使用します。
oao 14年

別のオプションは、問題を結合として再構成することです。参加は、はるかに高速パンダであるstackoverflow.com/questions/23945493/...
ブライアンSpiering

さらに別のオプションは、np.in1dを使用することです。これは、stackoverflow.com
Brian Spiering

回答:


8

残念ながら、パンダでは並列化はまだ実装されていません。あなたは参加することができ、このgithubの問題をあなたは、この機能の開発に参加したい場合。

この目的のための「魔法のユニコーンパッケージ」は知らないので、最善の方法は独自のソリューションを作成することです。それでもまだ時間をかけたくなくて、新しいことを学びたい場合は、MongoDBに組み込まれている2つのメソッド(map reduceおよびaggフレームワーク)を試すことができます。mongodb_agg_frameworkを参照してください。




0

パンダの適用機能の並列化に関するこの質問のより一般的なバージョンがあります-これはさわやかな質問です:)

最初に、「パッケージ化された」ソリューションを要求したのでswifterに言及したいと思います。それは、パンダの並列化に関するほとんどのSO質問に現れます。

しかし.. DataFrameでの数年間の作業の後、100%の並列化ソリューション(主に適用機能用)を見つけられず、常に「マニュアル」コード。

あなたのおかげで、(理論的には)DataFrameメソッドをその名前でサポートするように汎用化しました(したがって、isin、applyなどのバージョンを保持する必要はありません)。

python 2.7と3.6の両方を使用して、「isin」、「apply」、「isna」関数でテストしました。20行未満で、「サブセット」や「njobs」などのパンダの命名規則に従いました。

「isin」の同等のコードとの時間比較も追加しましたが、この要点の約2倍遅いようです。

次の2つの機能が含まれます。

df_multi_core-これはあなたが呼ぶものです。受け入れます:

  1. dfオブジェクト
  2. 呼び出したい関数名
  3. 関数を実行できる列のサブセット(時間/メモリの削減に役立ちます)
  4. 並列に実行するジョブの数(-1またはすべてのコアで省略)
  5. dfの関数が受け入れる他のkwargs(「軸」など)

_df_splitこれは、実行中のモジュールに対してグローバルに配置する必要がある内部ヘルパー関数です(Pool.mapは「配置依存」です)、そうでない場合は内部で検索します。

ここに私の要点からのコードがあります(パンダの機能テストをさらに追加します):

import pandas as pd
import numpy as np
import multiprocessing
from functools import partial

def _df_split(tup_arg, **kwargs):
    split_ind, df_split, df_f_name = tup_arg
    return (split_ind, getattr(df_split, df_f_name)(**kwargs))

def df_multi_core(df, df_f_name, subset=None, njobs=-1, **kwargs):
    if njobs == -1:
        njobs = multiprocessing.cpu_count()
    pool = multiprocessing.Pool(processes=njobs)

    try:
        splits = np.array_split(df[subset], njobs)
    except ValueError:
        splits = np.array_split(df, njobs)

    pool_data = [(split_ind, df_split, df_f_name) for split_ind, df_split in enumerate(splits)]
    results = pool.map(partial(_df_split, **kwargs), pool_data)
    pool.close()
    pool.join()
    results = sorted(results, key=lambda x:x[0])
    results = pd.concat([split[1] for split in results])
    return results

Bellowは、並列化されたisinのテストコードであり、ネイティブ、マルチコアの要点、および夕暮れ時のパフォーマンスを比較します。8つの物理コアを持つI7マシンでは、X4倍のスピードアップが得られました。実際のデータで何が得られるのか聞きたいです!

from time import time

if __name__ == '__main__': 
    sep = '-' * 50

    # isin test
    N = 10000000
    df = pd.DataFrame({'c1': np.random.randint(low=1, high=N, size=N), 'c2': np.arange(N)})
    lookfor = np.random.randint(low=1, high=N, size=1000000)

    print('{}\ntesting pandas isin on {}\n{}'.format(sep, df.shape, sep))
    t1 = time()
    print('result\n{}'.format(df.isin(lookfor).sum()))
    t2 = time()
    print('time for native implementation {}\n{}'.format(round(t2 - t1, 2), sep))

    t3 = time()
    res = df_multi_core(df=df, df_f_name='isin', subset=['c1'], njobs=-1, values=lookfor)
    print('result\n{}'.format(res.sum()))
    t4 = time()
    print('time for multi core implementation {}\n{}'.format(round(t4 - t3, 2), sep))


    t5 = time()
    ddata = dd.from_pandas(df, npartitions=njobs)
    res = ddata.map_partitions(lambda df: df.apply(apply_f, axis=1)).compute(scheduler='processes')
    t6 = time()
    print('result random sample\n{}'.format(res.sample(n=3, random_state=0)))
    print('time for dask implementation {}\n{}'.format(round(t6 - t5, 2), sep))

--------------------------------------------------
testing pandas isin on (10000000, 2)
--------------------------------------------------
result
c1    953213
c2    951942
dtype: int64
time for native implementation 3.87
--------------------------------------------------
result
c1    953213
dtype: int64
time for multi core implementation 1.16
--------------------------------------------------
result
c1    953213
c2    951942
dtype: int64
time for dask implementation 2.88

@Therriault私はとDASK比較を追加しましたisin-コードスニペットは、「ISIN」が最も効果的であると思われる- 〜X1.75倍高速、その後(に比べDASK applyのみDASK速く、その後5%を得たことを機能)
モルク
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.