Hơn 3 năm trước, chúng tôi đã đăng một nghiên cứu so sánh về việc lặp lại dữ liệu Pandas bằng CPU. Bởi vì rất nhiều thứ đã phát triển kể từ năm 2018, bài đăng này là một bản cập nhật. Ví dụ phiên bản thẻ Pandas lúc đó là
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator11, bây giờ là
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator12. Ngoài ra, chúng tôi đã thêm một số tùy chọn khác
Dưới đây là danh sách tất cả các tùy chọn được thử nghiệm sau đây
- Pandas tích hợp vector hóa
- gấu trúc. Khung dữ liệu. lặp đi lặp lại
- gấu trúc. Khung dữ liệu. ứng dụng
- gấu trúc. Khung dữ liệu. lặp đi lặp lại
- cục mịch. apply_along_axis
- cục mịch. véc tơ hóa
- bản đồ
- nhanh hơn
- bóng tối. khung dữ liệu. map_partitions
- vùng cực. Khung dữ liệu. ứng dụng
- vector hóa tích hợp cực
- tê liệt
- Numba song song
- Cython
- Cython song song
Giới thiệu
Động lực
Trọng tâm là lặp qua các hàng của khung dữ liệu Pandas chứa một số dữ liệu số. Tất cả các phần tử của khung dữ liệu thuộc kiểu dữ liệu
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator13. Một hàm được áp dụng cho mỗi hàng, lấy các phần tử của hàng làm đầu vào, làm đối số vô hướng riêng biệt, dưới dạng một mảng hoặc dưới dạng Chuỗi Pandas. Tính toán trả về một giá trị vô hướng trên mỗi hàng, để quá trình cuối cùng trả về một chuỗi Pandas số có cùng chỉ mục với khung dữ liệu gốc. Đối với bài đăng này, một hàm đồ chơi tính toán định thức của ma trận thực đối xứng 3 nhân 3 được sử dụng
$$\begin{equation*} M = \begin{pmatrix} m_{1,1} & m_{1,2} & m_{1,3} \\\ m_{1,2} & m_{2,2
$$. M. = m_{1,1} [m_{2,2} , m_{3,3} - m_{2,3}^2] + m_{1,2} , [2 , m_{2,3} , m_
Đây là một triển khai python thuần túy của hàm thông minh hàng
def det_sym33[m11, m12, m13, m22, m23, m33]: """Compute the determinant of a real symmetric 3x3 matrix given its 6 upper triangular coefficients. """ return [ m11 * [m22 * m33 - m23**2] + m12 * [2.0 * m23 * m13 - m12 * m33] - m22 * m13**2 ]
nhập khẩu
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator
Python version : 3.9.10
IPython version : 8.0.1
polars : 0.12.19
numpy : 1.21.5
swifter : 1.0.9
pandas : 1.4.1
cython : 0.29.28
numba : 0.55.1
perfplot : 0.10.1
dask : 2022.2.1
Tính toán được thực hiện trên máy tính xách tay có CPU Intel i7-7700HQ 8 nhân @ 2. 80GHz, chạy Linux
chức năng hẹn giờ
Hàm này đang trả về thời gian trôi qua tốt nhất trong _______ 14 thử nghiệm và kết quả tính toán
def timing[func, df, r=10]: timings = [] for i in range[r]: start = perf_counter[] s = func[df] end = perf_counter[] elapsed_time = end - start timings.append[elapsed_time] return s, np.amin[timings]
Tạo một khung dữ liệu với số float ngẫu nhiên
Chúng tôi bắt đầu bằng cách tạo một khung dữ liệu cỡ trung bình để thực hiện so sánh đầu tiên. Sau này chúng tôi sẽ so sánh các phương pháp hiệu quả nhất với các khung dữ liệu dài hơn
________số 8_______
CPU times: user 10.2 ms, sys: 143 µs, total: 10.4 ms
Wall time: 7.99 ms
df.head[3]
m11m12m13m22m23m3300. 7852530. 7858590. 9691360. 7480600. 6555510. 93888510. 1786140. 5886470. 4427990. 3488470. 3309290. 15936920. 9894630. 2571110. 7157650. 5058850. 6641110. 702342
Các hàm theo hàng
Bây giờ chúng ta tạo 3 hàm thông minh theo hàng khác nhau, với các loại đối số khác nhau cho các giá trị hàng đầu vào
- đối số vô hướng riêng biệt
- một mảng
- một loạt gấu trúc
def det_sym33_scalars[m11, m12, m13, m22, m23, m33]: return [ m11 * [m22 * m33 - m23**2] + m12 * [2.0 * m23 * m13 - m12 * m33] - m22 * m13**2 ]
def det_sym33_array[m]: return [ m[0] * [m[3] * m[5] - m[4] ** 2] + m[1] * [2.0 * m[4] * m[2] - m[1] * m[5]] - m[3] * m[2] ** 2 ]
def det_sym33_series[s]: return [ s.m11 * [s.m22 * s.m33 - s.m23**2] + s.m12 * [2.0 * s.m23 * s.m13 - s.m12 * s.m33] - s.m22 * s.m13**2 ]
Trong phần sau đây, chúng tôi có thể thử một số hàm thông minh theo hàng này cho một phương thức lặp khung dữ liệu nhất định, tùy thuộc vào cách phương thức trả về các hàng khung dữ liệu
Pandas tích hợp vector hóa
Trước tiên, chúng ta sẽ sử dụng các hoạt động vector hóa tích hợp từ Pandas. Trong trường hợp hiện tại, việc tính toán theo hàng đơn giản và có thể được thực hiện với các hàm phổ quát cơ bản được áp dụng cho toàn bộ cột. Điều này không sử dụng bất kỳ chức năng theo hàng nào, nhưng cho phép chúng tôi có thời gian tham chiếu
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator0
Chúng tôi lưu trữ Sê-ri Pandas kết quả vào biến
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator15, để kiểm tra xem các tính toán sau này có dẫn đến kết quả tương tự không
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator1
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator2
gấu trúc. Khung dữ liệu. lặp đi lặp lại
Chúng tôi biết rằng phương pháp
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator16 hơi chậm [ví dụ xem bài viết trước]. Nó lặp qua các hàng của khung dữ liệu dưới dạng các cặp [chỉ mục, Sê-ri]. Ở đây, chúng ta sẽ so sánh 3 loại đối số khác nhau của hàm thông minh theo hàng, với điều kiện là hàng được trả về bởi
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator16 là Chuỗi Pandas
- giá trị vô hướng
- một mảng Numpy
- một loạt gấu trúc
đối số vô hướng
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator3
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator4
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator5
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
cục mịch. đối số ndarray
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator7
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator8
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator9
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
gấu trúc. Đối số chuỗi
Python version : 3.9.10
IPython version : 8.0.1
polars : 0.12.19
numpy : 1.21.5
swifter : 1.0.9
pandas : 1.4.1
cython : 0.29.28
numba : 0.55.1
perfplot : 0.10.1
dask : 2022.2.1
1Python version : 3.9.10
IPython version : 8.0.1
polars : 0.12.19
numpy : 1.21.5
swifter : 1.0.9
pandas : 1.4.1
cython : 0.29.28
numba : 0.55.1
perfplot : 0.10.1
dask : 2022.2.1
2Python version : 3.9.10
IPython version : 8.0.1
polars : 0.12.19
numpy : 1.21.5
swifter : 1.0.9
pandas : 1.4.1
cython : 0.29.28
numba : 0.55.1
perfplot : 0.10.1
dask : 2022.2.1
3from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
so sánh
Python version : 3.9.10
IPython version : 8.0.1
polars : 0.12.19
numpy : 1.21.5
swifter : 1.0.9
pandas : 1.4.1
cython : 0.29.28
numba : 0.55.1
perfplot : 0.10.1
dask : 2022.2.1
5Chúng tôi quan sát thấy rằng bằng cách sử dụng mảng giá trị từ pandas. Sê-ri làm đối số của hàm theo hàng và truy cập dữ liệu bằng các chỉ số là phương pháp nhanh nhất khi sử dụng
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator18. Tuy nhiên, cả ba phương pháp
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator16 đều rất chậm
gấu trúc. Khung dữ liệu. ứng dụng
Phương thức
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator20 cũng lặp lại trên các hàng của khung dữ liệu [với đối số
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator21], trả về Sê-ri [mặc định] hoặc một mảng [với
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator22]. Đây là những gì tài liệu của Pandas nói về nó
tên hàm, phương thức trả về hàng dưới dạng hàm đối số, loại áp dụng_seriespd. Khung dữ liệu. áp dụng. Sê-ridet_sym33_seriespd. Seriesapply_arraypd. Khung dữ liệu. áp dụng. ndarraydet_sym33_arrayarraythay vào đó, chức năng được truyền sẽ nhận các đối tượng ndarray. Nếu bạn chỉ áp dụng chức năng giảm NumPy, điều này sẽ đạt được hiệu suất tốt hơn nhiều
gấu trúc. Đối số chuỗi
Python version : 3.9.10
IPython version : 8.0.1
polars : 0.12.19
numpy : 1.21.5
swifter : 1.0.9
pandas : 1.4.1
cython : 0.29.28
numba : 0.55.1
perfplot : 0.10.1
dask : 2022.2.1
6Python version : 3.9.10
IPython version : 8.0.1
polars : 0.12.19
numpy : 1.21.5
swifter : 1.0.9
pandas : 1.4.1
cython : 0.29.28
numba : 0.55.1
perfplot : 0.10.1
dask : 2022.2.1
7Python version : 3.9.10
IPython version : 8.0.1
polars : 0.12.19
numpy : 1.21.5
swifter : 1.0.9
pandas : 1.4.1
cython : 0.29.28
numba : 0.55.1
perfplot : 0.10.1
dask : 2022.2.1
8from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
cục mịch. đối số ndarray
def timing[func, df, r=10]: timings = [] for i in range[r]: start = perf_counter[] s = func[df] end = perf_counter[] elapsed_time = end - start timings.append[elapsed_time] return s, np.amin[timings]0
def timing[func, df, r=10]: timings = [] for i in range[r]: start = perf_counter[] s = func[df] end = perf_counter[] elapsed_time = end - start timings.append[elapsed_time] return s, np.amin[timings]1
def timing[func, df, r=10]: timings = [] for i in range[r]: start = perf_counter[] s = func[df] end = perf_counter[] elapsed_time = end - start timings.append[elapsed_time] return s, np.amin[timings]2
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
so sánh
def timing[func, df, r=10]: timings = [] for i in range[r]: start = perf_counter[] s = func[df] end = perf_counter[] elapsed_time = end - start timings.append[elapsed_time] return s, np.amin[timings]4
Thật vậy, sử dụng mảng thay vì Sê-ri nhanh hơn nhiều. Nhưng vẫn chậm hơn rất nhiều so với vector hóa tích hợp sẵn của gấu trúc
gấu trúc. Khung dữ liệu. lặp đi lặp lại
Phương thức
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator23 cho phép lặp lại trên các hàng của khung dữ liệu, trả về chúng dưới dạng các bộ được đặt tên. Do đó, các giá trị hàng có thể được truy cập theo tên hoặc theo chỉ mục. Hàm
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator24 và
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator25 được sử dụng trong trường hợp trước và
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator26 trong trường hợp sautên hàmphương pháp trả về các hàng như hàm theo chiều dọc đối số typeitertuples_scalarspd. Khung dữ liệu. itertuplesnamedtupledet_sym33_scalarsfloat64itertuples_arraypd. Khung dữ liệu. itertuplesnamedtupledet_sym33_arrayarrayitertuples_seriespd. Khung dữ liệu. itertuplesnamedtupledet_sym33_seriespd. Loạt
đối số vô hướng
def timing[func, df, r=10]: timings = [] for i in range[r]: start = perf_counter[] s = func[df] end = perf_counter[] elapsed_time = end - start timings.append[elapsed_time] return s, np.amin[timings]5
def timing[func, df, r=10]: timings = [] for i in range[r]: start = perf_counter[] s = func[df] end = perf_counter[] elapsed_time = end - start timings.append[elapsed_time] return s, np.amin[timings]6
def timing[func, df, r=10]: timings = [] for i in range[r]: start = perf_counter[] s = func[df] end = perf_counter[] elapsed_time = end - start timings.append[elapsed_time] return s, np.amin[timings]7
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
cục mịch. đối số mảng
Khi các giá trị hàng được truy cập theo chỉ mục, chúng ta cần tính đến chỉ mục khung dữ liệu, được lập chỉ mục bằng 0
def timing[func, df, r=10]: timings = [] for i in range[r]: start = perf_counter[] s = func[df] end = perf_counter[] elapsed_time = end - start timings.append[elapsed_time] return s, np.amin[timings]9
%%time n = 100_000 # dataframe length column_names = ['m11', 'm12', 'm13', 'm22', 'm23', 'm33'] df = pd.DataFrame[data=rng.random[[n, 6]], columns=column_names]0
%%time n = 100_000 # dataframe length column_names = ['m11', 'm12', 'm13', 'm22', 'm23', 'm33'] df = pd.DataFrame[data=rng.random[[n, 6]], columns=column_names]1
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
gấu trúc. Đối số chuỗi
%%time n = 100_000 # dataframe length column_names = ['m11', 'm12', 'm13', 'm22', 'm23', 'm33'] df = pd.DataFrame[data=rng.random[[n, 6]], columns=column_names]3
%%time n = 100_000 # dataframe length column_names = ['m11', 'm12', 'm13', 'm22', 'm23', 'm33'] df = pd.DataFrame[data=rng.random[[n, 6]], columns=column_names]4
%%time n = 100_000 # dataframe length column_names = ['m11', 'm12', 'm13', 'm22', 'm23', 'm33'] df = pd.DataFrame[data=rng.random[[n, 6]], columns=column_names]5
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
so sánh
%%time n = 100_000 # dataframe length column_names = ['m11', 'm12', 'm13', 'm22', 'm23', 'm33'] df = pd.DataFrame[data=rng.random[[n, 6]], columns=column_names]7
Chúng tôi nhận được loại kết quả tương tự với 3 loại đối số khác nhau. Một lần nữa, chúng ta có thể nói rằng
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator23 được ưu tiên hơn
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator16 và
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator20
cục mịch. apply_along_axis
Hãy thử phương pháp này cho phép áp dụng hàm cho lát cắt 1D dọc theo một trục đã cho [các hàng của mảng 2D trong trường hợp của chúng tôi]
tên hàmphương pháp trả về hàng dưới dạng tham số chức năng theo chiều dọc typenp_apply_along_axisnp. áp dụng_along_axisnp. ndarraydet_sym33_arrayarray%%time n = 100_000 # dataframe length column_names = ['m11', 'm12', 'm13', 'm22', 'm23', 'm33'] df = pd.DataFrame[data=rng.random[[n, 6]], columns=column_names]8
%%time n = 100_000 # dataframe length column_names = ['m11', 'm12', 'm13', 'm22', 'm23', 'm33'] df = pd.DataFrame[data=rng.random[[n, 6]], columns=column_names]9
CPU times: user 10.2 ms, sys: 143 µs, total: 10.4 ms
Wall time: 7.99 ms
0from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
Chà, điều này khá chậm và đáng thất vọng
cục mịch. véc tơ hóa
Numpy vectorize đánh giá hàm theo hàng trên từng phần tử của [các] mảng numpy đầu vào. Tuy nhiên, lưu ý cảnh báo trên tài liệu NumPy
tên hàmphương pháp trả về hàng dưới dạng hàm đối số thông minh typenp_vectorize_scalarsnp. vectorizefloat64det_sym33_scalarsfloat64np_vectorize_arraynp. vectorizenp. ndarraydet_sym33_arrayarrayChức năng vectorize được cung cấp chủ yếu để thuận tiện, không phải để thực hiện. Việc thực hiện về cơ bản là một vòng lặp for
đối số vô hướng
CPU times: user 10.2 ms, sys: 143 µs, total: 10.4 ms
Wall time: 7.99 ms
2CPU times: user 10.2 ms, sys: 143 µs, total: 10.4 ms
Wall time: 7.99 ms
3CPU times: user 10.2 ms, sys: 143 µs, total: 10.4 ms
Wall time: 7.99 ms
4from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
cục mịch. đối số ndarray
Trong trường hợp này, chúng ta cần thêm đối số
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator30 để chỉ định hình dạng đầu vào của hàm theo hàng
CPU times: user 10.2 ms, sys: 143 µs, total: 10.4 ms
Wall time: 7.99 ms
6CPU times: user 10.2 ms, sys: 143 µs, total: 10.4 ms
Wall time: 7.99 ms
7CPU times: user 10.2 ms, sys: 143 µs, total: 10.4 ms
Wall time: 7.99 ms
8from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
so sánh
df.head[3]0
Phiên bản với đối số vô hướng khá thú vị, nhanh hơn
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator23
bản đồ
Hãy sử dụng phương pháp Python tiêu chuẩn
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator32tên hàmphương pháp trả về hàng dưới dạng hàm đối số thông minh typemap_scalarsmapfloat64det_sym33_scalarsfloat64
df.head[3]1
df.head[3]2
df.head[3]3
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
Hiệu suất có vẻ giống nhau giữa
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator33 và
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator34
nhanh hơn
Swifter là một "gói áp dụng hiệu quả bất kỳ chức năng nào cho chuỗi hoặc khung dữ liệu gấu trúc theo cách nhanh nhất hiện có". chúng tôi sử dụng đối số
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator22. Đây là một trích dẫn từ các tài liệu
tên hàmphương pháp trả về các hàng như hàm theo chiều dọccác loại đối sốwifter_applyswifter. áp dụng. ndarraydet_sym33_arrayarraythô. bool, mặc định Sai
Sai. chuyển từng hàng hoặc cột dưới dạng Sê-ri cho hàm
Thật. thay vào đó, chức năng được truyền sẽ nhận các đối tượng ndarray. Nếu bạn chỉ áp dụng chức năng giảm NumPy, điều này sẽ đạt được hiệu suất tốt hơn nhiều
df.head[3]5
df.head[3]6
df.head[3]7
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
Quá trình tính toán khá chậm, có lẽ chúng tôi đang thiếu thứ gì đó ở đây và không sử dụng đúng gói này?
bóng tối. khung dữ liệu. map_partitions
Chúng tôi đã cố gắng sử dụng thư viện dask tuyệt vời với phương pháp
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator36. Thật không may, chúng tôi đã không hoàn toàn tìm ra cách xử lý đối số
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator37. Đây là mô tả từ tài liệu
meta. pd. Khung dữ liệu, pd. Chuỗi, dict, iterable, tuple, tùy chọn Một pd trống. Khung dữ liệu hoặc pd. Chuỗi phù hợp với dtypes và tên cột của đầu ra. Siêu dữ liệu này là cần thiết để nhiều thuật toán trong khung dữ liệu dask hoạt động. Để dễ sử dụng, một số đầu vào thay thế cũng có sẵn. Thay vì một DataFrame, một lệnh của {name. dtype} hoặc có thể lặp lại [name, dtype] có thể được cung cấp [lưu ý rằng thứ tự của các tên phải khớp với thứ tự của các cột]. Thay vì một chuỗi, có thể sử dụng một bộ [tên, dtype]. Nếu không được cung cấp, dask sẽ cố suy luận siêu dữ liệu. Điều này có thể dẫn đến kết quả không mong muốn, vì vậy nên cung cấp meta. Để biết thêm thông tin, xem dask. khung dữ liệu. đồ dùng. make_meta
Việc triển khai sau đây không hoạt động nhưng có thể có nhiều cách hiệu quả hơn để thực hiện
tên hàmphương pháp trả về hàng dưới dạng hàm đối số thông minh typedask_df_map_partitionsdd. map_partitionspd. Sê-ridet_sym33_seriespd. Loạtdf.head[3]9
def det_sym33_scalars[m11, m12, m13, m22, m23, m33]: return [ m11 * [m22 * m33 - m23**2] + m12 * [2.0 * m23 * m13 - m12 * m33] - m22 * m13**2 ]0
def det_sym33_scalars[m11, m12, m13, m22, m23, m33]: return [ m11 * [m22 * m33 - m23**2] + m12 * [2.0 * m23 * m13 - m12 * m33] - m22 * m13**2 ]1
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
Không quá tệ nhưng vẫn chậm hơn so với vector hóa tích hợp Pandas. Đây là những gì có thể được tìm thấy trên tài liệu dask
Lưu ý rằng, mặc dù song song, Dask. khung dữ liệu có thể không phải lúc nào cũng nhanh hơn Pandas. Chúng tôi khuyên bạn nên ở lại với Pandas càng lâu càng tốt trước khi chuyển sang Dask. khung dữ liệu
Ngoài ra, chúng tôi đoán rằng có thể có một bản sao khung dữ liệu từ Pandas sang Dask?
vùng cực. Khung dữ liệu. ứng dụng
Polars là một thư viện DataFrame đa luồng nhanh được viết bằng Rust nhưng cũng có sẵn bằng Python và Node. js. Ở đây chúng tôi sẽ sử dụng
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator38 cho phép áp dụng chức năng tùy chỉnh trên các hàng của Khung dữ liệu Polars. Các hàng được truyền dưới dạng Tuple. Tuy nhiên, hãy lưu ý cảnh báo này từ tài liệu của Polars
tên hàmphương pháp trả về các hàng như hàm đối số kiểu phân cực_applypolars. Khung dữ liệu. áp dụng [] tupledet_sym33_arrayarrayHãy coi chừng, điều này là chậm
def det_sym33_scalars[m11, m12, m13, m22, m23, m33]: return [ m11 * [m22 * m33 - m23**2] + m12 * [2.0 * m23 * m13 - m12 * m33] - m22 * m13**2 ]3
def det_sym33_scalars[m11, m12, m13, m22, m23, m33]: return [ m11 * [m22 * m33 - m23**2] + m12 * [2.0 * m23 * m13 - m12 * m33] - m22 * m13**2 ]4
def det_sym33_scalars[m11, m12, m13, m22, m23, m33]: return [ m11 * [m22 * m33 - m23**2] + m12 * [2.0 * m23 * m13 - m12 * m33] - m22 * m13**2 ]5
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
Điều này không quá tệ nhưng người ta có thể tự hỏi liệu phần lớn thời gian đã trôi qua không được dành để chuyển đổi khung dữ liệu từ Pandas sang Polars và ngược lại. Hãy đo thời gian đã trôi qua trên mỗi dòng bằng trình lược tả dòng
def det_sym33_scalars[m11, m12, m13, m22, m23, m33]: return [ m11 * [m22 * m33 - m23**2] + m12 * [2.0 * m23 * m13 - m12 * m33] - m22 * m13**2 ]7
def det_sym33_scalars[m11, m12, m13, m22, m23, m33]: return [ m11 * [m22 * m33 - m23**2] + m12 * [2.0 * m23 * m13 - m12 * m33] - m22 * m13**2 ]8
Hầu hết thời gian thực sự được sử dụng trong phương pháp
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator20. Tuy nhiên, chúng tôi tin rằng có một quy trình sao chép trong bước
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator40, điều này sẽ không tối ưu về việc sử dụng bộ nhớ?
Vector hóa các cực
Chúng tôi cũng có thể sử dụng véc tơ tích hợp Polars giống như cách chúng tôi đã làm với Pandas. Điều này không sử dụng các chức năng theo hàng trước đó
def det_sym33_scalars[m11, m12, m13, m22, m23, m33]: return [ m11 * [m22 * m33 - m23**2] + m12 * [2.0 * m23 * m13 - m12 * m33] - m22 * m13**2 ]9
def det_sym33_array[m]: return [ m[0] * [m[3] * m[5] - m[4] ** 2] + m[1] * [2.0 * m[4] * m[2] - m[1] * m[5]] - m[3] * m[2] ** 2 ]0
def det_sym33_array[m]: return [ m[0] * [m[3] * m[5] - m[4] ** 2] + m[1] * [2.0 * m[4] * m[2] - m[1] * m[5]] - m[3] * m[2] ** 2 ]1
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
Nếu chúng tôi chạy trình cấu hình dòng, chúng tôi có thể quan sát thấy rằng phần lớn thời gian đã trôi qua hiện được dành để chuyển đổi khung dữ liệu giữa Pandas và polars
def det_sym33_array[m]: return [ m[0] * [m[3] * m[5] - m[4] ** 2] + m[1] * [2.0 * m[4] * m[2] - m[1] * m[5]] - m[3] * m[2] ** 2 ]3
def det_sym33_array[m]: return [ m[0] * [m[3] * m[5] - m[4] ** 2] + m[1] * [2.0 * m[4] * m[2] - m[1] * m[5]] - m[3] * m[2] ** 2 ]4
tê liệt
Numba làm cho mã Python nhanh. Ở đây, chúng tôi sử dụng trình trang trí Numba
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator41 với
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator42 cho chức năng thông minh theo hàng chuyên dụng của Numba. Trong hàm
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator43, về cơ bản, chúng tôi triển khai vòng lặp trên các hàng của khung dữ liệu
def det_sym33_array[m]: return [ m[0] * [m[3] * m[5] - m[4] ** 2] + m[1] * [2.0 * m[4] * m[2] - m[1] * m[5]] - m[3] * m[2] ** 2 ]5
def det_sym33_array[m]: return [ m[0] * [m[3] * m[5] - m[4] ** 2] + m[1] * [2.0 * m[4] * m[2] - m[1] * m[5]] - m[3] * m[2] ** 2 ]6
def det_sym33_array[m]: return [ m[0] * [m[3] * m[5] - m[4] ** 2] + m[1] * [2.0 * m[4] * m[2] - m[1] * m[5]] - m[3] * m[2] ** 2 ]7
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
Vâng, đây là triển khai nhanh nhất cho đến nay
Numba song song
Bây giờ chúng ta sử dụng trình trang trí Numba
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator44 cùng với vòng lặp
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator45. Theo mặc định, tất cả các lõi có sẵn đều được sử dụng. Hàm thông minh hàng trước
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator43 được sử dụng ở đây
def det_sym33_array[m]: return [ m[0] * [m[3] * m[5] - m[4] ** 2] + m[1] * [2.0 * m[4] * m[2] - m[1] * m[5]] - m[3] * m[2] ** 2 ]9
def det_sym33_series[s]: return [ s.m11 * [s.m22 * s.m33 - s.m23**2] + s.m12 * [2.0 * s.m23 * s.m13 - s.m12 * s.m33] - s.m22 * s.m13**2 ]0
def det_sym33_series[s]: return [ s.m11 * [s.m22 * s.m33 - s.m23**2] + s.m12 * [2.0 * s.m23 * s.m13 - s.m12 * s.m33] - s.m22 * s.m13**2 ]1
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
Phiên bản song song không phải là một cải tiến lớn so với phiên bản Numba tuần tự. Điều này có thể là do kích thước tương đối nhỏ của khung dữ liệu
Cython
Cython là sự pha trộn giữa C và Python. Viết mã Cython liên quan nhiều hơn một chút so với viết Python thuần túy. Lưu ý rằng trong phần sau, chúng tôi đã sử dụng lệnh ma thuật
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator47 ở đầu ô sổ ghi chép để biên dịch mã Cython [chúng tôi cũng đã tải phần mở rộng Cython ở đầu sổ ghi chép]
def det_sym33_series[s]: return [ s.m11 * [s.m22 * s.m33 - s.m23**2] + s.m12 * [2.0 * s.m23 * s.m13 - s.m12 * s.m33] - s.m22 * s.m13**2 ]3
def det_sym33_series[s]: return [ s.m11 * [s.m22 * s.m33 - s.m23**2] + s.m12 * [2.0 * s.m23 * s.m13 - s.m12 * s.m33] - s.m22 * s.m13**2 ]4
def det_sym33_series[s]: return [ s.m11 * [s.m22 * s.m33 - s.m23**2] + s.m12 * [2.0 * s.m23 * s.m13 - s.m12 * s.m33] - s.m22 * s.m13**2 ]5
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator6
Điều này không nhanh như Numba nhưng gần
Cython song song
Tương tự như những gì chúng ta đã làm với Numba, ở đây chúng ta sử dụng hàm lặp
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator45. Đây là một trích dẫn từ các tài liệu
con trăn. song song, tương đông. prange[[start,] stop[, step][, nogil=False][, schedule=None[, chunksize=None]][, num_threads=None]]
Chức năng này có thể được sử dụng cho các vòng lặp song song. OpenMP tự động bắt đầu nhóm luồng và phân phối công việc theo lịch trình được sử dụng. Chủ đề cục bộ và giảm được tự động suy ra cho các biến
def det_sym33_series[s]: return [ s.m11 * [s.m22 * s.m33 - s.m23**2] + s.m12 * [2.0 * s.m23 * s.m13 - s.m12 * s.m33] - s.m22 * s.m13**2 ]7
def det_sym33_series[s]: return [ s.m11 * [s.m22 * s.m33 - s.m23**2] + s.m12 * [2.0 * s.m23 * s.m13 - s.m12 * s.m33] - s.m22 * s.m13**2 ]8
def det_sym33_series[s]: return [ s.m11 * [s.m22 * s.m33 - s.m23**2] + s.m12 * [2.0 * s.m23 * s.m13 - s.m12 * s.m33] - s.m22 * s.m13**2 ]9
Phiên bản song song nhanh hơn một chút so với phiên bản tuần tự nhưng chúng ta nên kiểm tra nó trên các khung dữ liệu lớn hơn
so sánh toàn cầu
Chúng tôi bắt đầu bằng cách so sánh tất cả các phương pháp trên các khung dữ liệu kích thước nhỏ
Khung dữ liệu kích thước nhỏ
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator00
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator01
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator02
Chỉ có các phương thức Numba và Cython là nhanh hơn đáng kể so với vector hóa dựng sẵn của Pandas [
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator49]
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator03
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator04
100010000iterrows_array2. 50e-022. 76e-01swifter_apply4. 08e-034. 41e-02apply_array3. 56e-033. 75e-02np_apply_along_axis2. 79e-033. 71e-02dask_df_map_partitions1. 11e-021. 92e-02itertuples_scalars1. 66e-031. 56e-02poles_apply2. 82e-031. 21e-02map_scalars9. 42e-049. 08e-03np_vectorize_scalars7. 03e-046. 39e-03poles_vectorize2. 39e-032. 30e-03pandas_vectorize1. 50e-031. 52e-03numba_loop_para1. 68e-041. 84e-04cython_loop_para1. 43e-041. 81e-04cython_loop1. 06e-041. 20e-04numba_loop8. 01e-059. 84e-05
Khung dữ liệu kích thước trung bình đến lớn
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator05
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator02
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator04
100000010000000pandas_vectorize3. 95e-024. 10e-01numba_loop3. 92e-037. 33e-02cython_loop4. 40e-035. 29e-02cython_loop_para3. 21e-033. 55e-02numba_loop_para2. 35e-032. 53e-02
Hãy tập trung vào các phương pháp Numba và Cython
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator08
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator09
from itertools import cycle from time import perf_counter import cython import dask.dataframe as dd from numba import jit, float64, njit, prange import numpy as np import perfplot import pandas as pd import polars as pl import swifter %load_ext Cython %load_ext line_profiler SD = 124 # random seed rng = np.random.default_rng[SD] # random number generator10
Phần kết luận
Pandas tích hợp vector hóa là một giải pháp rất tốt khi có thể. Nếu chúng ta muốn nhanh hơn mà không đau thêm, Numba là giải pháp tốt nhất. Cython nhanh như Numba, linh hoạt, nhưng liên quan nhiều hơn