Python vượt qua hàng khung dữ liệu để hoạt động
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 Show
Dưới đây là danh sách tất cả các tùy chọn được thử nghiệm sau đây
Giới thiệuĐộng lựcTrọ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ẩufrom 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
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ênChú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_______
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àngBâ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
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óaTrướ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ạiChú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
đối số vô hướngfrom 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ố ndarrayfrom 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 1 2 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 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ụngPhươ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_arrayarray gấu trúc. Đối số chuỗi 6 7 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ố ndarraydef 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ánhdef 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ạiPhươ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ướngdef 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ảngKhi 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_axisHã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 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óaNumpy 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_arrayarray đối số vô hướng 2 3 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ố ndarrayTrong 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 6 7 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ánhdf.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ơnSwifter 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_arrayarray 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_partitionsChú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
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
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ụngPolars 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_arrayarray 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ựcChú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ệtNumba 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 songBâ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 CythonCython 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 songTươ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
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ầuChú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ớnfrom 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ậnPandas 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 |