Có một phiên bản phổ biến hơn của câu hỏi này liên quan đến việc song song hóa chức năng áp dụng gấu trúc - vì vậy đây là một câu hỏi mới mẻ :)
Đầu tiên , tôi muốn đề cập đến swifter vì bạn đã yêu cầu giải pháp "đóng gói" và nó xuất hiện trên hầu hết các câu hỏi SO liên quan đến song song gấu trúc.
Nhưng .. Tôi vẫn muốn chia sẻ mã chính của mình cho nó, vì sau vài năm làm việc với DataFrame, tôi chưa bao giờ tìm thấy giải pháp song song 100% (chủ yếu cho chức năng áp dụng) và tôi luôn phải quay lại với " hướng dẫn sử dụng "mã.
Nhờ có bạn, tôi đã làm cho nó chung chung hơn để hỗ trợ bất kỳ phương thức DataFrame nào (về mặt lý thuyết) theo tên của nó (vì vậy bạn sẽ không phải giữ các phiên bản cho isin, áp dụng, v.v.).
Tôi đã thử nghiệm nó trên các hàm "isin", "áp dụng" và "isna" bằng cả hai python 2.7 và 3.6. Đó là dưới 20 dòng, và tôi đã theo quy ước đặt tên gấu trúc như "tập hợp con" và "njobs".
Tôi cũng đã thêm một so sánh thời gian với mã tương đương dask cho "isin" và có vẻ như ~ X2 lần chậm hơn ý chính này.
Nó bao gồm 2 chức năng:
df_multi_core - đây là người bạn gọi. Nó chấp nhận:
- Đối tượng df của bạn
- Tên hàm bạn muốn gọi
- Tập hợp con của cột có thể được thực hiện theo (giúp giảm thời gian / bộ nhớ)
- Số lượng công việc chạy song song (-1 hoặc bỏ qua cho tất cả các lõi)
- Bất kỳ kwarg nào khác chức năng của df đều chấp nhận (như "trục")
_df_split - đây là chức năng của trình trợ giúp nội bộ phải được định vị toàn cầu cho mô-đun đang chạy (Pool.map là "phụ thuộc vị trí"), nếu không tôi sẽ xác định vị trí bên trong ..
đây là mã từ ý chính của tôi (Tôi sẽ thêm nhiều bài kiểm tra chức năng gấu trúc ở đó):
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 là một mã kiểm tra cho một isin song song , so sánh hiệu suất chính, đa lõi và hiệu suất dask. Trên máy I7 với 8 lõi vật lý, tôi đã tăng tốc khoảng X4 lần. Tôi rất muốn nghe những gì bạn nhận được trên dữ liệu thực của bạn!
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