Được gõ python nhanh hơn

Trong phần này của hướng dẫn, chúng tôi sẽ điều tra cách tăng tốc một số chức năng hoạt động trên gấu trúc bằng ba kỹ thuật khác nhau. Cython, Numba và. Chúng ta sẽ thấy tốc độ cải thiện ~200 khi chúng ta sử dụng Cython và Numba trên chức năng kiểm tra hoạt động theo hàng trên. Sử dụng, chúng tôi sẽ tăng tốc một khoản tiền theo thứ tự ~2

Ghi chú

Ngoài việc làm theo các bước trong hướng dẫn này, người dùng quan tâm đến việc nâng cao hiệu suất được khuyến khích cài đặt for pandas. Các phụ thuộc này thường không được cài đặt theo mặc định, nhưng sẽ cải thiện tốc độ nếu có

Cython (viết phần mở rộng C cho gấu trúc)

Đối với nhiều trường hợp sử dụng, viết pandas bằng Python và NumPy thuần túy là đủ. Tuy nhiên, trong một số ứng dụng nặng tính toán, có thể đạt được tốc độ tăng đáng kể bằng cách giảm tải công việc cho cython

Hướng dẫn này giả định rằng bạn đã tái cấu trúc càng nhiều càng tốt trong Python, chẳng hạn bằng cách cố gắng loại bỏ các vòng lặp for và sử dụng vector hóa NumPy. Trước tiên, luôn đáng để tối ưu hóa trong Python

Hướng dẫn này trình bày một quy trình “điển hình” của việc tạo cython cho một tính toán chậm. Chúng tôi sử dụng một ví dụ từ tài liệu Cython nhưng trong bối cảnh gấu trúc. Giải pháp cythonized cuối cùng của chúng tôi nhanh hơn khoảng 100 lần so với giải pháp Python thuần túy

Trăn tinh

Chúng tôi có một cái mà chúng tôi muốn áp dụng một chức năng theo hàng

In [1]: df = pd.DataFrame(
   ...:     {
   ...:         "a": np.random.randn(1000),
   ...:         "b": np.random.randn(1000),
   ...:         "N": np.random.randint(100, 1000, (1000)),
   ...:         "x": "x",
   ...:     }
   ...: )
   ...: 

In [2]: df
Out[2]: 
            a         b    N  x
0    0.469112 -0.218470  585  x
1   -0.282863 -0.061645  841  x
2   -1.509059 -0.723780  251  x
3   -1.135632  0.551225  972  x
4    1.212112 -0.497767  181  x
.        ..       ..  .. ..
995 -1.512743  0.874737  374  x
996  0.933753  1.120790  246  x
997 -0.308013  0.198768  157  x
998 -0.079915  1.757555  977  x
999 -1.010589 -1.115680  770  x

[1000 rows x 4 columns]

Đây là chức năng trong Python thuần túy

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 

Chúng tôi đạt được kết quả của mình bằng cách sử dụng (hàng khôn ngoan)

In [5]: %timeit df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
86 ms +- 1.44 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)

Nhưng rõ ràng điều này không đủ nhanh đối với chúng tôi. Hãy xem và xem thời gian được sử dụng ở đâu trong quá trình thao tác này (giới hạn ở bốn cuộc gọi tốn nhiều thời gian nhất) bằng cách sử dụng

In [6]: %prun -l 4 df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)  # noqa E999
         621327 function calls (621307 primitive calls) in 0.168 seconds

   Ordered by: internal time
   List reduced from 225 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1000    0.093    0.000    0.143    0.000 <ipython-input-4-c2a74e076cf0>:1(integrate_f)
   552423    0.050    0.000    0.050    0.000 <ipython-input-3-c138bdd570e3>:1(f)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)

Cho đến nay, phần lớn thời gian được sử dụng bên trong

In [8]: %%cython
   ...: def f_plain(x):
   ...:     return x * (x - 1)
   ...: def integrate_f_plain(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f_plain(a + i * dx)
   ...:     return s * dx
   ...: 
2 hoặc
In [8]: %%cython
   ...: def f_plain(x):
   ...:     return x * (x - 1)
   ...: def integrate_f_plain(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f_plain(a + i * dx)
   ...:     return s * dx
   ...: 
3, do đó chúng tôi sẽ tập trung nỗ lực của mình vào việc mã hóa hai chức năng này

Đồng bằng Cython

Trước tiên, chúng ta sẽ cần nhập hàm ma thuật Cython vào IPython

In [7]: %load_ext Cython

Bây giờ, chúng ta chỉ cần sao chép các chức năng của chúng ta sang Cython (hậu tố ở đây để phân biệt giữa các phiên bản chức năng)

In [8]: %%cython
   ...: def f_plain(x):
   ...:     return x * (x - 1)
   ...: def integrate_f_plain(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f_plain(a + i * dx)
   ...:     return s * dx
   ...: 

Ghi chú

Nếu bạn gặp sự cố khi dán phần trên vào ipython của mình, bạn có thể cần phải sử dụng IPython cạnh chảy máu để dán để chơi tốt với ma thuật di động

________số 8_______

Điều này đã loại bỏ một phần ba, không quá tệ đối với một bản sao và dán đơn giản

Thêm loại

Chúng tôi nhận được một cải tiến lớn khác chỉ đơn giản bằng cách cung cấp thông tin loại

In [10]: %%cython
   ....: cdef double f_typed(double x) except? -2:
   ....:     return x * (x - 1)
   ....: cpdef double integrate_f_typed(double a, double b, int N):
   ....:     cdef int i
   ....:     cdef double s, dx
   ....:     s = 0
   ....:     dx = (b - a) / N
   ....:     for i in range(N):
   ....:         s += f_typed(a + i * dx)
   ....:     return s * dx
   ....: 

In [11]: %timeit df.apply(lambda x: integrate_f_typed(x["a"], x["b"], x["N"]), axis=1)
9.47 ms +- 279 us per loop (mean +- std. dev. of 7 runs, 100 loops each)

Bây giờ chúng ta nói chuyện. Nó hiện nhanh hơn mười lần so với triển khai Python ban đầu và chúng tôi chưa thực sự sửa đổi mã. Chúng ta hãy có một cái nhìn khác về những gì đang ăn hết thời gian

In [12]: %prun -l 4 df.apply(lambda x: integrate_f_typed(x["a"], x["b"], x["N"]), axis=1)
         68904 function calls (68884 primitive calls) in 0.026 seconds

   Ordered by: internal time
   List reduced from 224 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
    16174    0.002    0.000    0.003    0.000 {built-in method builtins.isinstance}
     3000    0.002    0.000    0.003    0.000 base.py:3754(get_loc)

sử dụng ndarray

Nó gọi hàng loạt rất nhiều. Nó đang tạo một từ mỗi hàng và gọi get từ cả chỉ mục và chuỗi (ba lần cho mỗi hàng). Các cuộc gọi hàm rất tốn kém trong Python, vì vậy có lẽ chúng ta có thể giảm thiểu chúng bằng cách cythonizing phần áp dụng

Ghi chú

Chúng tôi hiện đang chuyển ndarrays vào hàm Cython, may mắn thay Cython chơi rất tốt với NumPy

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
0

Việc triển khai rất đơn giản, nó tạo ra một mảng các số không và lặp qua các hàng, áp dụng

In [8]: %%cython
   ...: def f_plain(x):
   ...:     return x * (x - 1)
   ...: def integrate_f_plain(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f_plain(a + i * dx)
   ...:     return s * dx
   ...: 
5 của chúng tôi và đặt số này vào mảng số không

Cảnh báo

Bạn không thể chuyển trực tiếp dưới dạng tham số đã nhập

In [8]: %%cython
   ...: def f_plain(x):
   ...:     return x * (x - 1)
   ...: def integrate_f_plain(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f_plain(a + i * dx)
   ...:     return s * dx
   ...: 
7 cho hàm Cython. Thay vào đó, vượt qua
In [8]: %%cython
   ...: def f_plain(x):
   ...:     return x * (x - 1)
   ...: def integrate_f_plain(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f_plain(a + i * dx)
   ...:     return s * dx
   ...: 
7 thực tế bằng cách sử dụng. Lý do là định nghĩa Cython dành riêng cho ndarray chứ không phải định nghĩa đã qua

Vì vậy, không làm điều này

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
1

Nhưng thay vào đó, sử dụng để lấy

In [8]: %%cython
   ...: def f_plain(x):
   ...:     return x * (x - 1)
   ...: def integrate_f_plain(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f_plain(a + i * dx)
   ...:     return s * dx
   ...: 
7 cơ bản

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
2

Ghi chú

Các vòng lặp như thế này sẽ cực kỳ chậm trong Python, nhưng trong Cython, việc lặp qua các mảng NumPy rất nhanh

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
3

Chúng tôi đã nhận được một cải tiến lớn khác. Hãy kiểm tra lại xem thời gian đã được sử dụng ở đâu

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
4

Như mọi người có thể mong đợi, phần lớn thời gian hiện được dành cho

In [9]: %timeit df.apply(lambda x: integrate_f_plain(x["a"], x["b"], x["N"]), axis=1)
50.9 ms +- 160 us per loop (mean +- std. dev. of 7 runs, 10 loops each)
3, vì vậy nếu chúng tôi muốn đạt được hiệu quả cao hơn nữa, chúng tôi phải tiếp tục tập trung nỗ lực vào đây

Các kỹ thuật nâng cao hơn

Vẫn còn hy vọng cải thiện. Đây là một ví dụ về việc sử dụng một số kỹ thuật Cython nâng cao hơn

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
5

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
6

Thậm chí còn nhanh hơn, với lời cảnh báo rằng một lỗi trong mã Cython của chúng tôi (ví dụ: lỗi từng lỗi một) có thể gây ra lỗi phân tách vì quyền truy cập bộ nhớ không được kiểm tra. Để biết thêm về

In [9]: %timeit df.apply(lambda x: integrate_f_plain(x["a"], x["b"], x["N"]), axis=1)
50.9 ms +- 160 us per loop (mean +- std. dev. of 7 runs, 10 loops each)
4 và
In [9]: %timeit df.apply(lambda x: integrate_f_plain(x["a"], x["b"], x["N"]), axis=1)
50.9 ms +- 160 us per loop (mean +- std. dev. of 7 runs, 10 loops each)
5, hãy xem tài liệu Cython trên

Numba (biên dịch JIT)

Một giải pháp thay thế cho mã Cython biên dịch tĩnh là sử dụng trình biên dịch động just-in-time (JIT) với Numba

Numba cho phép bạn viết một hàm Python thuần túy có thể được biên dịch JIT thành các hướng dẫn máy gốc, có hiệu suất tương tự như C, C++ và Fortran, bằng cách tô điểm cho hàm của bạn bằng

In [9]: %timeit df.apply(lambda x: integrate_f_plain(x["a"], x["b"], x["N"]), axis=1)
50.9 ms +- 160 us per loop (mean +- std. dev. of 7 runs, 10 loops each)
6

Numba hoạt động bằng cách tạo mã máy được tối ưu hóa bằng cơ sở hạ tầng trình biên dịch LLVM tại thời điểm nhập, thời gian chạy hoặc tĩnh (sử dụng công cụ pycc đi kèm). Numba hỗ trợ biên dịch Python để chạy trên phần cứng CPU hoặc GPU và được thiết kế để tích hợp với ngăn xếp phần mềm khoa học Python

Ghi chú

Quá trình biên dịch

In [9]: %timeit df.apply(lambda x: integrate_f_plain(x["a"], x["b"], x["N"]), axis=1)
50.9 ms +- 160 us per loop (mean +- std. dev. of 7 runs, 10 loops each)
6 sẽ thêm chi phí hoạt động vào thời gian chạy của hàm, do đó, lợi ích về hiệu suất có thể không được nhận ra, đặc biệt là khi sử dụng các tập dữ liệu nhỏ. Xem xét lưu trữ chức năng của bạn vào bộ đệm để tránh chi phí biên dịch mỗi khi chức năng của bạn được chạy

Numba có thể được sử dụng theo 2 cách với gấu trúc

  1. Chỉ định từ khóa

    In [9]: %timeit df.apply(lambda x: integrate_f_plain(x["a"], x["b"], x["N"]), axis=1)
    50.9 ms +- 160 us per loop (mean +- std. dev. of 7 runs, 10 loops each)
    
    8 trong các phương pháp chọn gấu trúc

  2. Xác định hàm Python của riêng bạn được trang trí bằng

    In [9]: %timeit df.apply(lambda x: integrate_f_plain(x["a"], x["b"], x["N"]), axis=1)
    50.9 ms +- 160 us per loop (mean +- std. dev. of 7 runs, 10 loops each)
    
    6 và chuyển mảng NumPy bên dưới hoặc (sử dụng
    In [10]: %%cython
       ....: cdef double f_typed(double x) except? -2:
       ....:     return x * (x - 1)
       ....: cpdef double integrate_f_typed(double a, double b, int N):
       ....:     cdef int i
       ....:     cdef double s, dx
       ....:     s = 0
       ....:     dx = (b - a) / N
       ....:     for i in range(N):
       ....:         s += f_typed(a + i * dx)
       ....:     return s * dx
       ....: 
    
    2) vào hàm

gấu trúc Numba Engine

Nếu Numba được cài đặt, người ta có thể chỉ định

In [9]: %timeit df.apply(lambda x: integrate_f_plain(x["a"], x["b"], x["N"]), axis=1)
50.9 ms +- 160 us per loop (mean +- std. dev. of 7 runs, 10 loops each)
8 trong các phương thức gấu trúc đã chọn để thực thi phương thức bằng Numba. Các phương thức hỗ trợ
In [9]: %timeit df.apply(lambda x: integrate_f_plain(x["a"], x["b"], x["N"]), axis=1)
50.9 ms +- 160 us per loop (mean +- std. dev. of 7 runs, 10 loops each)
8 cũng sẽ có một từ khóa
In [10]: %%cython
   ....: cdef double f_typed(double x) except? -2:
   ....:     return x * (x - 1)
   ....: cpdef double integrate_f_typed(double a, double b, int N):
   ....:     cdef int i
   ....:     cdef double s, dx
   ....:     s = 0
   ....:     dx = (b - a) / N
   ....:     for i in range(N):
   ....:         s += f_typed(a + i * dx)
   ....:     return s * dx
   ....: 
5 chấp nhận một từ điển cho phép một người chỉ định các khóa
In [10]: %%cython
   ....: cdef double f_typed(double x) except? -2:
   ....:     return x * (x - 1)
   ....: cpdef double integrate_f_typed(double a, double b, int N):
   ....:     cdef int i
   ....:     cdef double s, dx
   ....:     s = 0
   ....:     dx = (b - a) / N
   ....:     for i in range(N):
   ....:         s += f_typed(a + i * dx)
   ....:     return s * dx
   ....: 
6,
In [10]: %%cython
   ....: cdef double f_typed(double x) except? -2:
   ....:     return x * (x - 1)
   ....: cpdef double integrate_f_typed(double a, double b, int N):
   ....:     cdef int i
   ....:     cdef double s, dx
   ....:     s = 0
   ....:     dx = (b - a) / N
   ....:     for i in range(N):
   ....:         s += f_typed(a + i * dx)
   ....:     return s * dx
   ....: 
7 và
In [10]: %%cython
   ....: cdef double f_typed(double x) except? -2:
   ....:     return x * (x - 1)
   ....: cpdef double integrate_f_typed(double a, double b, int N):
   ....:     cdef int i
   ....:     cdef double s, dx
   ....:     s = 0
   ....:     dx = (b - a) / N
   ....:     for i in range(N):
   ....:         s += f_typed(a + i * dx)
   ....:     return s * dx
   ....: 
8 với các giá trị boolean để chuyển vào trình trang trí
In [9]: %timeit df.apply(lambda x: integrate_f_plain(x["a"], x["b"], x["N"]), axis=1)
50.9 ms +- 160 us per loop (mean +- std. dev. of 7 runs, 10 loops each)
6. Nếu
In [10]: %%cython
   ....: cdef double f_typed(double x) except? -2:
   ....:     return x * (x - 1)
   ....: cpdef double integrate_f_typed(double a, double b, int N):
   ....:     cdef int i
   ....:     cdef double s, dx
   ....:     s = 0
   ....:     dx = (b - a) / N
   ....:     for i in range(N):
   ....:         s += f_typed(a + i * dx)
   ....:     return s * dx
   ....: 
5 không được chỉ định, nó sẽ mặc định là
In [11]: %timeit df.apply(lambda x: integrate_f_typed(x["a"], x["b"], x["N"]), axis=1)
9.47 ms +- 279 us per loop (mean +- std. dev. of 7 runs, 100 loops each)
1 trừ khi được chỉ định khác

Về mặt hiệu suất, lần đầu tiên một chức năng được chạy bằng công cụ Numba sẽ chậm vì Numba sẽ có một số chi phí biên dịch chức năng. Tuy nhiên, các chức năng được biên dịch JIT được lưu vào bộ đệm và các cuộc gọi tiếp theo sẽ nhanh chóng. Nói chung, công cụ Numba hoạt động hiệu quả với số lượng điểm dữ liệu lớn hơn (e. g. hơn 1 triệu)

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
7

Nếu phần cứng máy tính của bạn chứa nhiều CPU, bạn có thể đạt được mức tăng hiệu suất lớn nhất bằng cách đặt

In [11]: %timeit df.apply(lambda x: integrate_f_typed(x["a"], x["b"], x["N"]), axis=1)
9.47 ms +- 279 us per loop (mean +- std. dev. of 7 runs, 100 loops each)
2 thành
In [11]: %timeit df.apply(lambda x: integrate_f_typed(x["a"], x["b"], x["N"]), axis=1)
9.47 ms +- 279 us per loop (mean +- std. dev. of 7 runs, 100 loops each)
3 để tận dụng nhiều hơn 1 CPU. Trong nội bộ, gấu trúc tận dụng tê để song song hóa các phép tính trên các cột của a ;

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
8

Ví dụ về chức năng tùy chỉnh

Có thể sử dụng một hàm Python tùy chỉnh được trang trí bằng

In [9]: %timeit df.apply(lambda x: integrate_f_plain(x["a"], x["b"], x["N"]), axis=1)
50.9 ms +- 160 us per loop (mean +- std. dev. of 7 runs, 10 loops each)
6 với các đối tượng pandas bằng cách chuyển các biểu diễn mảng NumPy của chúng với
In [10]: %%cython
   ....: cdef double f_typed(double x) except? -2:
   ....:     return x * (x - 1)
   ....: cpdef double integrate_f_typed(double a, double b, int N):
   ....:     cdef int i
   ....:     cdef double s, dx
   ....:     s = 0
   ....:     dx = (b - a) / N
   ....:     for i in range(N):
   ....:         s += f_typed(a + i * dx)
   ....:     return s * dx
   ....: 
2

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
9

In [5]: %timeit df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
86 ms +- 1.44 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)
0

Trong ví dụ này, sử dụng Numba nhanh hơn Cython

Numba cũng có thể được sử dụng để viết các hàm vector hóa không yêu cầu người dùng lặp lại một cách rõ ràng các quan sát của một vector; . Xem xét ví dụ sau về việc nhân đôi mỗi quan sát

In [5]: %timeit df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
86 ms +- 1.44 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)
1

In [5]: %timeit df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
86 ms +- 1.44 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)
2

Hãy cẩn thận

Numba là cách tốt nhất để tăng tốc các hàm áp dụng các hàm số cho mảng NumPy. Nếu bạn cố gắng

In [9]: %timeit df.apply(lambda x: integrate_f_plain(x["a"], x["b"], x["N"]), axis=1)
50.9 ms +- 160 us per loop (mean +- std. dev. of 7 runs, 10 loops each)
6 một hàm chứa mã Python hoặc NumPy không được hỗ trợ, quá trình biên dịch sẽ hoàn nguyên, điều này hầu như sẽ không tăng tốc chức năng của bạn. Nếu bạn muốn Numba đưa ra lỗi nếu nó không thể biên dịch một hàm theo cách tăng tốc mã của bạn, hãy chuyển cho Numba đối số
In [11]: %timeit df.apply(lambda x: integrate_f_typed(x["a"], x["b"], x["N"]), axis=1)
9.47 ms +- 279 us per loop (mean +- std. dev. of 7 runs, 100 loops each)
9 (e. g.
In [12]: %prun -l 4 df.apply(lambda x: integrate_f_typed(x["a"], x["b"], x["N"]), axis=1)
         68904 function calls (68884 primitive calls) in 0.026 seconds

   Ordered by: internal time
   List reduced from 224 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
    16174    0.002    0.000    0.003    0.000 {built-in method builtins.isinstance}
     3000    0.002    0.000    0.003    0.000 base.py:3754(get_loc)
0). Để biết thêm về khắc phục sự cố chế độ Numba, hãy xem phần

Sử dụng

In [12]: %prun -l 4 df.apply(lambda x: integrate_f_typed(x["a"], x["b"], x["N"]), axis=1)
         68904 function calls (68884 primitive calls) in 0.026 seconds

   Ordered by: internal time
   List reduced from 224 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
    16174    0.002    0.000    0.003    0.000 {built-in method builtins.isinstance}
     3000    0.002    0.000    0.003    0.000 base.py:3754(get_loc)
1 (e. g.
In [12]: %prun -l 4 df.apply(lambda x: integrate_f_typed(x["a"], x["b"], x["N"]), axis=1)
         68904 function calls (68884 primitive calls) in 0.026 seconds

   Ordered by: internal time
   List reduced from 224 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
    16174    0.002    0.000    0.003    0.000 {built-in method builtins.isinstance}
     3000    0.002    0.000    0.003    0.000 base.py:3754(get_loc)
2) có thể dẫn đến
In [12]: %prun -l 4 df.apply(lambda x: integrate_f_typed(x["a"], x["b"], x["N"]), axis=1)
         68904 function calls (68884 primitive calls) in 0.026 seconds

   Ordered by: internal time
   List reduced from 224 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
    16174    0.002    0.000    0.003    0.000 {built-in method builtins.isinstance}
     3000    0.002    0.000    0.003    0.000 base.py:3754(get_loc)
3 nếu lớp luồng dẫn đến hành vi không an toàn. Trước tiên, bạn có thể chạy một chức năng JIT với
In [12]: %prun -l 4 df.apply(lambda x: integrate_f_typed(x["a"], x["b"], x["N"]), axis=1)
         68904 function calls (68884 primitive calls) in 0.026 seconds

   Ordered by: internal time
   List reduced from 224 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
    16174    0.002    0.000    0.003    0.000 {built-in method builtins.isinstance}
     3000    0.002    0.000    0.003    0.000 base.py:3754(get_loc)
1

Nói chung, nếu bạn gặp phải một segfault (

In [12]: %prun -l 4 df.apply(lambda x: integrate_f_typed(x["a"], x["b"], x["N"]), axis=1)
         68904 function calls (68884 primitive calls) in 0.026 seconds

   Ordered by: internal time
   List reduced from 224 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
    16174    0.002    0.000    0.003    0.000 {built-in method builtins.isinstance}
     3000    0.002    0.000    0.003    0.000 base.py:3754(get_loc)
5) trong khi sử dụng Numba, vui lòng báo cáo sự cố cho trình theo dõi sự cố Numba

Đánh giá biểu hiện thông qua

Hàm cấp cao nhất thực hiện đánh giá biểu thức của và các đối tượng

Ghi chú

Để hưởng lợi từ việc sử dụng, bạn cần cài đặt

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
01. Xem để biết thêm chi tiết

Điểm sử dụng để đánh giá biểu thức thay vì Python đơn giản là hai lần. 1) các đối tượng lớn được đánh giá hiệu quả hơn và 2) các biểu thức số học và boolean lớn được đánh giá tất cả cùng một lúc bởi công cụ bên dưới (theo mặc định ____________01 được sử dụng để đánh giá)

Ghi chú

Bạn không nên sử dụng cho các biểu thức đơn giản hoặc cho các biểu thức liên quan đến DataFrames nhỏ. Trên thực tế, chậm hơn nhiều bậc đối với các biểu thức/đối tượng nhỏ hơn so với Python đơn giản. Một nguyên tắc nhỏ là chỉ sử dụng khi bạn có hơn 10.000 hàng

hỗ trợ tất cả các biểu thức số học được công cụ hỗ trợ ngoài một số tiện ích mở rộng chỉ có trong gấu trúc

Ghi chú

Khung càng lớn và biểu thức càng lớn, bạn sẽ thấy tốc độ càng nhanh khi sử dụng

Cú pháp được hỗ trợ

Các hoạt động này được hỗ trợ bởi

  • Các phép toán số học ngoại trừ toán tử dịch trái (

    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    12) và dịch phải (
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    13), e. g. ,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    14

  • Các hoạt động so sánh, bao gồm so sánh chuỗi, e. g. ,

    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    15

  • Phép toán Boolean, e. g. ,

    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    16

  • In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    17 và
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    18 chữ thường, e. g. ,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    19 hoặc
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    20

  • Quyền truy cập thuộc tính, e. g. ,

    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    21

  • biểu thức chỉ số, e. g. ,

    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    22

  • Đánh giá biến đơn giản, e. g. ,

    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    23 (điều này không hữu ích lắm)

  • hàm toán học.

    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    24,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    25,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    26,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    27,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    28,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    29,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    30,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    31,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    32,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    33,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    34,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    35,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    36,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    37,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    38,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    39,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    34,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    40,
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    42 và
    In [3]: def f(x):
       ...:     return x * (x - 1)
       ...: 
    
    In [4]: def integrate_f(a, b, N):
       ...:     s = 0
       ...:     dx = (b - a) / N
       ...:     for i in range(N):
       ...:         s += f(a + i * dx)
       ...:     return s * dx
       ...: 
    
    42

Cú pháp Python này không được phép

  • Biểu thức

    • Các lệnh gọi hàm khác với các hàm toán học

    • Hoạt động

      In [3]: def f(x):
         ...:     return x * (x - 1)
         ...: 
      
      In [4]: def integrate_f(a, b, N):
         ...:     s = 0
         ...:     dx = (b - a) / N
         ...:     for i in range(N):
         ...:         s += f(a + i * dx)
         ...:     return s * dx
         ...: 
      
      43/
      In [3]: def f(x):
         ...:     return x * (x - 1)
         ...: 
      
      In [4]: def integrate_f(a, b, N):
         ...:     s = 0
         ...:     dx = (b - a) / N
         ...:     for i in range(N):
         ...:         s += f(a + i * dx)
         ...:     return s * dx
         ...: 
      
      44

    • In [3]: def f(x):
         ...:     return x * (x - 1)
         ...: 
      
      In [4]: def integrate_f(a, b, N):
         ...:     s = 0
         ...:     dx = (b - a) / N
         ...:     for i in range(N):
         ...:         s += f(a + i * dx)
         ...:     return s * dx
         ...: 
      
      45 biểu thức

    • In [3]: def f(x):
         ...:     return x * (x - 1)
         ...: 
      
      In [4]: def integrate_f(a, b, N):
         ...:     s = 0
         ...:     dx = (b - a) / N
         ...:     for i in range(N):
         ...:         s += f(a + i * dx)
         ...:     return s * dx
         ...: 
      
      46 biểu thức

    • In [3]: def f(x):
         ...:     return x * (x - 1)
         ...: 
      
      In [4]: def integrate_f(a, b, N):
         ...:     s = 0
         ...:     dx = (b - a) / N
         ...:     for i in range(N):
         ...:         s += f(a + i * dx)
         ...:     return s * dx
         ...: 
      
      17/
      In [3]: def f(x):
         ...:     return x * (x - 1)
         ...: 
      
      In [4]: def integrate_f(a, b, N):
         ...:     s = 0
         ...:     dx = (b - a) / N
         ...:     for i in range(N):
         ...:         s += f(a + i * dx)
         ...:     return s * dx
         ...: 
      
      48/
      In [3]: def f(x):
         ...:     return x * (x - 1)
         ...: 
      
      In [4]: def integrate_f(a, b, N):
         ...:     s = 0
         ...:     dx = (b - a) / N
         ...:     for i in range(N):
         ...:         s += f(a + i * dx)
         ...:     return s * dx
         ...: 
      
      49 comprehensions

    • Các biểu thức

      In [3]: def f(x):
         ...:     return x * (x - 1)
         ...: 
      
      In [4]: def integrate_f(a, b, N):
         ...:     s = 0
         ...:     dx = (b - a) / N
         ...:     for i in range(N):
         ...:         s += f(a + i * dx)
         ...:     return s * dx
         ...: 
      
      49 và
      In [3]: def f(x):
         ...:     return x * (x - 1)
         ...: 
      
      In [4]: def integrate_f(a, b, N):
         ...:     s = 0
         ...:     dx = (b - a) / N
         ...:     for i in range(N):
         ...:         s += f(a + i * dx)
         ...:     return s * dx
         ...: 
      
      48 theo nghĩa đen

    • In [3]: def f(x):
         ...:     return x * (x - 1)
         ...: 
      
      In [4]: def integrate_f(a, b, N):
         ...:     s = 0
         ...:     dx = (b - a) / N
         ...:     for i in range(N):
         ...:         s += f(a + i * dx)
         ...:     return s * dx
         ...: 
      
      52 biểu thức

    • biểu thức trình tạo

    • Biểu thức Boolean chỉ bao gồm các giá trị vô hướng

  • Các câu lệnh

    • Không cho phép câu lệnh đơn hay phức. Điều này bao gồm những thứ như

      In [3]: def f(x):
         ...:     return x * (x - 1)
         ...: 
      
      In [4]: def integrate_f(a, b, N):
         ...:     s = 0
         ...:     dx = (b - a) / N
         ...:     for i in range(N):
         ...:         s += f(a + i * dx)
         ...:     return s * dx
         ...: 
      
      53,
      In [3]: def f(x):
         ...:     return x * (x - 1)
         ...: 
      
      In [4]: def integrate_f(a, b, N):
         ...:     s = 0
         ...:     dx = (b - a) / N
         ...:     for i in range(N):
         ...:         s += f(a + i * dx)
         ...:     return s * dx
         ...: 
      
      54 và
      In [3]: def f(x):
         ...:     return x * (x - 1)
         ...: 
      
      In [4]: def integrate_f(a, b, N):
         ...:     s = 0
         ...:     dx = (b - a) / N
         ...:     for i in range(N):
         ...:         s += f(a + i * dx)
         ...:     return s * dx
         ...: 
      
      45

ví dụ

hoạt động tốt với các biểu thức chứa mảng lớn

Trước tiên, hãy tạo một vài mảng có kích thước phù hợp để chơi với

In [5]: %timeit df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
86 ms +- 1.44 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)
3

Bây giờ, hãy so sánh việc thêm chúng lại với nhau bằng cách sử dụng Python thuần túy so với

In [5]: %timeit df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
86 ms +- 1.44 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)
4

In [5]: %timeit df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
86 ms +- 1.44 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)
5

Bây giờ hãy làm điều tương tự nhưng với sự so sánh

In [5]: %timeit df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
86 ms +- 1.44 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)
6

In [5]: %timeit df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
86 ms +- 1.44 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)
7

cũng hoạt động với các đối tượng gấu trúc chưa được phân bổ

In [5]: %timeit df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
86 ms +- 1.44 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)
8

In [5]: %timeit df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
86 ms +- 1.44 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)
9

Ghi chú

Các thao tác như

In [6]: %prun -l 4 df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)  # noqa E999
         621327 function calls (621307 primitive calls) in 0.168 seconds

   Ordered by: internal time
   List reduced from 225 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1000    0.093    0.000    0.143    0.000 <ipython-input-4-c2a74e076cf0>:1(integrate_f)
   552423    0.050    0.000    0.050    0.000 <ipython-input-3-c138bdd570e3>:1(f)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
0

nên được thực hiện bằng Python. Một ngoại lệ sẽ được đưa ra nếu bạn cố gắng thực hiện bất kỳ thao tác boolean/bitwise nào với toán hạng vô hướng không thuộc loại

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
60 hoặc
In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
61. Một lần nữa, bạn nên thực hiện các loại thao tác này bằng Python thuần túy

phương pháp

Ngoài chức năng cấp cao nhất, bạn cũng có thể đánh giá một biểu thức trong “ngữ cảnh” của một

In [6]: %prun -l 4 df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)  # noqa E999
         621327 function calls (621307 primitive calls) in 0.168 seconds

   Ordered by: internal time
   List reduced from 225 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1000    0.093    0.000    0.143    0.000 <ipython-input-4-c2a74e076cf0>:1(integrate_f)
   552423    0.050    0.000    0.050    0.000 <ipython-input-3-c138bdd570e3>:1(f)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
1

Bất kỳ biểu thức nào là biểu thức hợp lệ cũng là biểu thức hợp lệ, với lợi ích bổ sung là bạn không phải thêm tiền tố vào tên của (các) cột mà bạn muốn đánh giá

Ngoài ra, bạn có thể thực hiện gán các cột trong một biểu thức. Điều này cho phép đánh giá công thức. Mục tiêu gán có thể là tên cột mới hoặc tên cột hiện có và nó phải là mã định danh Python hợp lệ

Từ khóa

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
68 xác định xem nhiệm vụ này sẽ được thực hiện trên bản gốc hay trả về một bản sao với cột mới

In [6]: %prun -l 4 df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)  # noqa E999
         621327 function calls (621307 primitive calls) in 0.168 seconds

   Ordered by: internal time
   List reduced from 225 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1000    0.093    0.000    0.143    0.000 <ipython-input-4-c2a74e076cf0>:1(integrate_f)
   552423    0.050    0.000    0.050    0.000 <ipython-input-3-c138bdd570e3>:1(f)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
2

Khi

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
68 được đặt thành
In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
71, theo mặc định, một bản sao của cột có cột mới hoặc cột đã sửa đổi được trả về và khung ban đầu không thay đổi

In [6]: %prun -l 4 df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)  # noqa E999
         621327 function calls (621307 primitive calls) in 0.168 seconds

   Ordered by: internal time
   List reduced from 225 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1000    0.093    0.000    0.143    0.000 <ipython-input-4-c2a74e076cf0>:1(integrate_f)
   552423    0.050    0.000    0.050    0.000 <ipython-input-3-c138bdd570e3>:1(f)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
3

Để thuận tiện, có thể thực hiện nhiều nhiệm vụ bằng cách sử dụng chuỗi nhiều dòng

In [6]: %prun -l 4 df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)  # noqa E999
         621327 function calls (621307 primitive calls) in 0.168 seconds

   Ordered by: internal time
   List reduced from 225 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1000    0.093    0.000    0.143    0.000 <ipython-input-4-c2a74e076cf0>:1(integrate_f)
   552423    0.050    0.000    0.050    0.000 <ipython-input-3-c138bdd570e3>:1(f)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
4

Tương đương trong tiêu chuẩn Python sẽ là

In [6]: %prun -l 4 df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)  # noqa E999
         621327 function calls (621307 primitive calls) in 0.168 seconds

   Ordered by: internal time
   List reduced from 225 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1000    0.093    0.000    0.143    0.000 <ipython-input-4-c2a74e076cf0>:1(integrate_f)
   552423    0.050    0.000    0.050    0.000 <ipython-input-3-c138bdd570e3>:1(f)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
5

Phương thức này có từ khóa

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
68 xác định xem truy vấn có sửa đổi khung ban đầu hay không

In [6]: %prun -l 4 df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)  # noqa E999
         621327 function calls (621307 primitive calls) in 0.168 seconds

   Ordered by: internal time
   List reduced from 225 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1000    0.093    0.000    0.143    0.000 <ipython-input-4-c2a74e076cf0>:1(integrate_f)
   552423    0.050    0.000    0.050    0.000 <ipython-input-3-c138bdd570e3>:1(f)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
6

Biến cục bộ

Bạn phải tham chiếu rõ ràng bất kỳ biến cục bộ nào mà bạn muốn sử dụng trong một biểu thức bằng cách đặt ký tự

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
75 trước tên. Ví dụ,

In [6]: %prun -l 4 df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)  # noqa E999
         621327 function calls (621307 primitive calls) in 0.168 seconds

   Ordered by: internal time
   List reduced from 225 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1000    0.093    0.000    0.143    0.000 <ipython-input-4-c2a74e076cf0>:1(integrate_f)
   552423    0.050    0.000    0.050    0.000 <ipython-input-3-c138bdd570e3>:1(f)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
7

Nếu bạn không đặt tiền tố cho biến cục bộ bằng

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
75, gấu trúc sẽ đưa ra một ngoại lệ cho bạn biết biến đó là không xác định

Khi sử dụng and , điều này cho phép bạn có một biến cục bộ và một cột có cùng tên trong một biểu thức

In [6]: %prun -l 4 df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)  # noqa E999
         621327 function calls (621307 primitive calls) in 0.168 seconds

   Ordered by: internal time
   List reduced from 225 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1000    0.093    0.000    0.143    0.000 <ipython-input-4-c2a74e076cf0>:1(integrate_f)
   552423    0.050    0.000    0.050    0.000 <ipython-input-3-c138bdd570e3>:1(f)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
8

Với bạn hoàn toàn không thể sử dụng tiền tố

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
75 vì nó không được định nghĩa trong ngữ cảnh đó. gấu trúc sẽ cho bạn biết điều này nếu bạn cố gắng sử dụng
In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
75 trong lệnh gọi cấp cao nhất tới. Ví dụ,

In [6]: %prun -l 4 df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)  # noqa E999
         621327 function calls (621307 primitive calls) in 0.168 seconds

   Ordered by: internal time
   List reduced from 225 to 4 due to restriction <4>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1000    0.093    0.000    0.143    0.000 <ipython-input-4-c2a74e076cf0>:1(integrate_f)
   552423    0.050    0.000    0.050    0.000 <ipython-input-3-c138bdd570e3>:1(f)
     3000    0.004    0.000    0.018    0.000 series.py:966(__getitem__)
     3000    0.002    0.000    0.009    0.000 series.py:1072(_get_value)
9

Trong trường hợp này, bạn chỉ nên tham khảo các biến giống như trong Python chuẩn

In [7]: %load_ext Cython
0

trình phân tích cú pháp

Có hai trình phân tích cú pháp khác nhau và hai công cụ khác nhau mà bạn có thể sử dụng làm phụ trợ

Trình phân tích cú pháp

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
85 mặc định cho phép một cú pháp trực quan hơn để thể hiện các hoạt động giống như truy vấn (so sánh, liên từ và phân tách). Cụ thể, mức độ ưu tiên của các toán tử
In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
86 và
In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
87 được tạo bằng với mức độ ưu tiên của các phép toán boolean tương ứng
In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
88 và
In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
89

Ví dụ, liên từ trên có thể được viết mà không có dấu ngoặc đơn. Ngoài ra, bạn có thể sử dụng trình phân tích cú pháp

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
90 để thực thi ngữ nghĩa Python nghiêm ngặt

In [7]: %load_ext Cython
1

Biểu thức tương tự cũng có thể được "anded" cùng với từ

In [7]: %load_ext Cython
2

Các toán tử

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
88 và
In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
89 ở đây có cùng mức độ ưu tiên như trong vanilla Python

phụ trợ

Ngoài ra còn có tùy chọn để làm cho hoạt động giống hệt với Python thuần túy

Ghi chú

Sử dụng công cụ

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
90 thường không hữu ích, ngoại trừ việc thử nghiệm các công cụ đánh giá khác chống lại nó. Bạn sẽ không đạt được lợi ích về hiệu suất khi sử dụng với
In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
98 và trên thực tế có thể bị ảnh hưởng về hiệu suất

Bạn có thể thấy điều này bằng cách sử dụng với công cụ

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
90. Nó chậm hơn một chút (không nhiều) so với việc đánh giá cùng một biểu thức trong Python

In [7]: %load_ext Cython
3

In [7]: %load_ext Cython
4

hiệu suất

được dự định để tăng tốc một số loại hoạt động. Đặc biệt, những hoạt động liên quan đến các biểu thức phức tạp với các đối tượng / lớn sẽ thấy lợi ích hiệu suất đáng kể. Đây là một biểu đồ hiển thị thời gian chạy dưới dạng hàm của kích thước của khung liên quan đến tính toán. Hai dòng là hai động cơ khác nhau

Được gõ python nhanh hơn

Ghi chú

Các thao tác với các đối tượng nhỏ (khoảng 15k-20k hàng) nhanh hơn khi sử dụng Python đơn giản

Được gõ python nhanh hơn

Biểu đồ này được tạo bằng cách sử dụng a với 3 cột, mỗi cột chứa các giá trị dấu phẩy động được tạo bằng cách sử dụng

In [5]: %timeit df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
86 ms +- 1.44 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)
07

Chi tiết kỹ thuật liên quan đến đánh giá biểu thức

Các biểu thức dẫn đến một đối tượng dtype hoặc liên quan đến các thao tác ngày giờ (vì

In [5]: %timeit df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
86 ms +- 1.44 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)
08) phải được đánh giá trong không gian Python. Lý do chính cho hành vi này là để duy trì khả năng tương thích ngược với các phiên bản NumPy < 1. 7. Trong các phiên bản NumPy đó, lệnh gọi tới ____2_______09 sẽ cắt bớt bất kỳ chuỗi nào dài hơn 60 ký tự. Thứ hai, chúng ta không thể chuyển mảng
In [5]: %timeit df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
86 ms +- 1.44 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)
10 sang
In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
01, do đó, phép so sánh chuỗi phải được đánh giá trong không gian Python

Kết quả là điều này chỉ áp dụng cho các biểu thức object-dtype. Vì vậy, nếu bạn có một biểu thức-ví dụ

In [7]: %load_ext Cython
5

phần số của phép so sánh (

In [5]: %timeit df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
86 ms +- 1.44 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)
12) sẽ được đánh giá bởi
In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
01

Nói chung, / sẽ đánh giá các biểu thức con có thể được đánh giá bởi

In [3]: def f(x):
   ...:     return x * (x - 1)
   ...: 

In [4]: def integrate_f(a, b, N):
   ...:     s = 0
   ...:     dx = (b - a) / N
   ...:     for i in range(N):
   ...:         s += f(a + i * dx)
   ...:     return s * dx
   ...: 
01 và những biểu thức con phải được đánh giá trong không gian Python một cách minh bạch đối với người dùng. Điều này được thực hiện bằng cách suy ra kiểu kết quả của một biểu thức từ các đối số và toán tử của nó