<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          讓 Pandas DataFrame 性能飛升 40 倍

          共 1530字,需瀏覽 4分鐘

           ·

          2020-12-04 20:53

          1. 小試牛刀
          大名鼎鼎的Pandas是數(shù)據(jù)分析的神器。有時候我們需要對上千萬甚至上億的數(shù)據(jù)進(jìn)行非常復(fù)雜處理,那么運(yùn)行效率就是一個不能忽視的問題。比如下面這個簡單例子,我們隨機(jī)生成100萬條數(shù)據(jù),對val這一列進(jìn)行處理:如果是偶數(shù)則減1,奇數(shù)則加1。實際的數(shù)據(jù)分析工作要比這個例子復(fù)雜的多,但考慮到我們沒有那么多時間等待運(yùn)行結(jié)果,所以就偷個懶吧??梢钥吹?/span>transform函數(shù)的平均運(yùn)行時間是284ms:
          import?pandas?as?pd
          import?numpy?as?np

          def?gen_data(size):
          ????d?=?dict()
          ????d["genre"]?=?np.random.choice(["A",?"B",?"C",?"D"],?size=size)
          ????d["val"]?=?np.random.randint(low=0,?high=100,?size=size)
          ????return?pd.DataFrame(d)

          data?=?gen_data(1000000)
          data.head()
          def?transform(data):
          ????data.loc[:,?"new_val"]?=?data.val.apply(lambda?x:?x?+?1?if?x?%?2?else?x?-?1)

          %timeit?-n?1?transform(data)
          284?ms?±?8.95?ms?per?loop?(mean?±?std.?dev.?of?7?runs,?1?loop?each)
          2. 用Cython編寫C擴(kuò)展
          試試用我們的老朋友Cython來寫一下 x + 1 if x % 2 else x - 1 這個函數(shù)。平均運(yùn)行時間降低到了202ms,果然速度變快了。性能大約提升了1.4倍,離40倍的flag還差的好遠(yuǎn)。
          %load_ext?cython
          %%cython
          cpdef?int?_transform(int?x):
          ????if?x?%?2:
          ????????return?x?+?1
          ????return?x?-?1

          def?transform(data):
          ????data.loc[:,?"new_val"]?=?data.val.apply(_transform)

          %timeit?-n?1?transform(data)
          202?ms?±?13.1?ms?per?loop?(mean?±?std.?dev.?of?7?runs,?1?loop?each)
          3. 減少類型轉(zhuǎn)換
          為了減少C和Python之間的類型轉(zhuǎn)換,我們直接把val這一列作為Numpy數(shù)組傳遞給Cython函數(shù),注意區(qū)分cnpnp。平均運(yùn)行時間直接降到10.8毫秒,性能大約提升了26倍,仿佛看到了一絲希望。
          %%cython
          import?numpy?as?np
          cimport?numpy?as?cnp
          ctypedef?cnp.int_t?DTYPE_t

          cpdef?cnp.ndarray[DTYPE_t]?_transform(cnp.ndarray[DTYPE_t]?arr):
          ????cdef:
          ????????int?i?=?0
          ????????int?n?=?arr.shape[0]
          ????????int?x
          ????????cnp.ndarray[DTYPE_t]?new_arr?=?np.empty_like(arr)

          ????while?i?????????x?=?arr[i]
          ????????if?x?%?2:
          ????????????new_arr[i]?=?x?+?1
          ????????else:
          ????????????new_arr[i]?=?x?-?1
          ????????i?+=?1
          ????return?new_arr

          def?transform(data):
          ????data.loc[:,?"new_val"]?=?_transform(data.val.values)

          %timeit?-n?1?transform(data)
          10.8?ms?±?512?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1?loop?each)
          4. 使用不安全的數(shù)組
          利用@cython.boundscheck(False),@cython.wraparound(False)裝飾器關(guān)閉數(shù)組的邊界檢查和負(fù)下標(biāo)處理,平均運(yùn)行時間變?yōu)?.9毫秒。性能提升了42倍左右,順利完成任務(wù)。
          %%cython
          import?cython
          import?numpy?as?np
          cimport?numpy?as?cnp
          ctypedef?cnp.int_t?DTYPE_t


          @cython.boundscheck(False)
          @cython.wraparound(False)
          cpdef?cnp.ndarray[DTYPE_t]?_transform(cnp.ndarray[DTYPE_t]?arr):
          ????cdef:
          ????????int?i?=?0
          ????????int?n?=?arr.shape[0]
          ????????int?x
          ????????cnp.ndarray[DTYPE_t]?new_arr?=?np.empty_like(arr)

          ????while?i?????????x?=?arr[i]
          ????????if?x?%?2:
          ????????????new_arr[i]?=?x?+?1
          ????????else:
          ????????????new_arr[i]?=?x?-?1
          ????????i?+=?1
          ????return?new_arr

          def?transform(data):
          ????data.loc[:,?"new_val"]?=?_transform(data.val.values)

          %timeit?-n?1?transform(data)
          6.76?ms?±?545?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1?loop?each)


          作者:李小文,先后從事過數(shù)據(jù)分析、數(shù)據(jù)挖掘工作,主要開發(fā)語言是Python,現(xiàn)任一家小型互聯(lián)網(wǎng)公司的算法工程師。

          Github:?https://github.com/tushushu


          推薦閱讀



          一行代碼讓 pandas 的 apply 速度飆到極致!


          用 Style 方法提高 Pandas 數(shù)據(jù)的顏值


          高性能 Pandas 方法:query 和 eval


          點擊下方閱讀原文加入社區(qū)會員




          點贊鼓勵一下

          瀏覽 82
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲狼人影院 | 影音先锋国产av 影音先锋麻豆传媒 | 91翔田千里 | 天天舔天天射 | 找找色亚洲 |