Pandalar üzerinde paralelleştirme ile ilgili bu sorunun daha yaygın bir sürümü var işlevi uygulayın - yani bu canlandırıcı bir soru :)
İlk , “paketlenmiş” bir çözüm istediğinizden bu yana kaygılanmaktan bahsetmek istiyorum ve pandaların paralelleşmesiyle ilgili çoğu SO sorusunda görünüyor.
Ama .. Yine de kişisel öz kodumu paylaşmak isterim, çünkü DataFrame ile birkaç yıl çalıştıktan sonra% 100 paralelleştirme çözümü asla bulamadım (esas olarak başvuru fonksiyonu için) ve her zaman benim için geri gelmek zorunda kaldım " manuel "kod.
Senin sayende (Teorik olarak) herhangi bir DataFrame yöntemini ismiyle desteklemeyi daha genel hale getirdim (böylece sürümleri isin, uygula, vb. İçin saklamana gerek kalmayacak).
Hem python 2.7 hem de 3.6 kullanarak "isin", "application" ve "isna" fonksiyonları üzerinde test ettim. 20 satırın altında ve ben "subset" ve "njobs" gibi kongre adındaki pandaları takip ettim.
Ayrıca "isin" için dask eşdeğer koduyla bir zaman karşılaştırması ekledim ve bu özlemden ~ X2 kat daha yavaş görünüyor.
2 işlev içerir:
df_multi_core - aradığınız kişi budur. Kabul eder:
- Df nesneniz
- Aramak istediğiniz işlev adı
- İşlevin gerçekleştirilebileceği sütun alt kümesi (zamanın / belleğin azaltılmasına yardımcı olur)
- Paralel olarak çalışacak işlerin sayısı (-1 veya tüm çekirdekler için ihmal)
- Df'nin işlevini kabul eden diğer herhangi bir kwargs ("eksen" gibi)
_df_split - bu, çalışan modülde global olarak konumlandırılması gereken dahili bir yardımcı işlevdir (Pool.map "yerleşime bağımlıdır"), aksi halde dahili olarak bulurdum.
işte bu benim özümden kod (orada daha fazla panda işlev testi ekleyeceğim):
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
Körük, doğal, çok çekirdekli öz ve dask performanslarını karşılaştıran bir paralelleştirilmiş isin için test kodudur . 8 fiziksel çekirdeğe sahip bir I7 makinede, X4 kat daha hızlandım. Gerçek verilerinde ne olduğunu duymayı çok isterim!
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