Cách đơn giản nhất là sử dụng map_partitions của Dask . Bạn cần những lần nhập này (bạn sẽ cần pip install dask
):
import pandas as pd
import dask.dataframe as dd
from dask.multiprocessing import get
và cú pháp là
data = <your_pandas_dataframe>
ddata = dd.from_pandas(data, npartitions=30)
def myfunc(x,y,z, ...): return <whatever>
res = ddata.map_partitions(lambda df: df.apply((lambda row: myfunc(*row)), axis=1)).compute(get=get)
(Tôi tin rằng 30 là số lượng phân vùng phù hợp nếu bạn có 16 lõi). Chỉ để hoàn thiện, tôi đã tính thời gian chênh lệch trên máy của mình (16 lõi):
data = pd.DataFrame()
data['col1'] = np.random.normal(size = 1500000)
data['col2'] = np.random.normal(size = 1500000)
ddata = dd.from_pandas(data, npartitions=30)
def myfunc(x,y): return y*(x**2+1)
def apply_myfunc_to_DF(df): return df.apply((lambda row: myfunc(*row)), axis=1)
def pandas_apply(): return apply_myfunc_to_DF(data)
def dask_apply(): return ddata.map_partitions(apply_myfunc_to_DF).compute(get=get)
def vectorized(): return myfunc(data['col1'], data['col2'] )
t_pds = timeit.Timer(lambda: pandas_apply())
print(t_pds.timeit(number=1))
28.16970546543598
t_dsk = timeit.Timer(lambda: dask_apply())
print(t_dsk.timeit(number=1))
2.708152851089835
t_vec = timeit.Timer(lambda: vectorized())
print(t_vec.timeit(number=1))
0,010668013244867325
Đưa ra hệ số 10 tốc độ đi từ gấu trúc áp dụng cho dask áp dụng trên các phân vùng. Tất nhiên, nếu bạn có một hàm mà bạn có thể vectơ hóa, thì bạn nên - trong trường hợp này, hàm ( y*(x**2+1)
) được vectơ hóa tầm thường, nhưng có rất nhiều thứ không thể vectơ hóa.