簡體   English   中英

pandas 數據幀的並行化操作

[英]Parallelizing operations for pandas dataframe

我有一個非常大的熊貓數據框,如下所示:

╔════════╦═════════════╦════════╗
║ index  ║    Users    ║ Income ║
╠════════╬═════════════╬════════╣
║ 0      ║ user_1      ║    304 ║
║ 1      ║ user_2      ║    299 ║
║ ...    ║             ║        ║
║ 399999 ║ user_400000 ║    542 ║
╚════════╩═════════════╩════════╝

(有幾列需要做一些計算)

因此,對於每個客戶端,我都必須應用大量的操作(移位、求和、減法、條件等),因此(據我所知)不可能對所有內容應用布爾屏蔽,我已經嘗試過,所以我的問題是可以按如下方式將 Pandas 數據幀分成塊,例如:

# chunk 1
╔════════╦═════════════╦════════╗
║ index  ║    Users    ║ Income ║
╠════════╬═════════════╬════════╣
║ 0      ║ user_1      ║    304 ║
║ 1      ║ user_2      ║    299 ║
║ ...    ║             ║        ║
║ 19999  ║ user_20000  ║    432 ║
╚════════╩═════════════╩════════╝

# chunk 2
╔════════╦═════════════╦════════╗
║ index  ║    Users    ║ Income ║
╠════════╬═════════════╬════════╣
║ 20000  ║ user_20000  ║    199 ║
║ 20001  ║ user_20001  ║    412 ║
║ ...    ║             ║        ║
║ 39999  ║ user_40000  ║    725 ║
╚════════╩═════════════╩════════╝

# chunk K 
╔════════╦═════════════╦════════╗
║ index  ║    Users    ║ Income ║
╠════════╬═════════════╬════════╣
║ ...    ║ user_...    ║    ... ║
║ ...    ║ user_...    ║    ... ║
║ ...    ║             ║        ║
║ ...    ║ user_...    ║    ... ║
╚════════╩═════════════╩════════╝

並並行應用所有這些塊的所有操作。

您可以使用多處理池來完成其中一些任務,但是,多處理也是一項昂貴的操作,因此您需要測試並行化它是否實際上更快,這取決於您正在運行的函數類型和數據,例如我創建了一個示例df

import pandas as pd
import numpy as np
from random import randint
from multiprocessing import Pool, cpu_count
from timeit import timeit


def f(df: pd.DataFrame):
    df['Something'] = df['Users'].apply(lambda name: len(name))
    df['Other stuff'] = df['Income'].apply(lambda income: 'Senior' if income > 200 else 'Junior')
    df['Some other stuff'] = df['Users'].apply(lambda name:  name.count('1'))
    return df


if __name__ == '__main__':
    samples = 5000000
    df = pd.DataFrame(
        [
            ['user_' + str(i), randint(0, 500)] for i in range(1, samples)
        ], columns=['Users', 'Income']
    )

如果我們使用多處理對這個版本的f函數38.189200899999996 ,我的舊筆記本電腦會得到38.189200899999996

    parallelized = timeit("""
cores = cpu_count()
df_in_chunks = np.array_split(df, cores)
pool = Pool(cores)
result_df = pd.concat(pool.map(f, df_in_chunks))
pool.close()
pool.join()
    """, 
    "from __main__ import pd, np, df, Pool, cpu_count, f", 
    number=5
    )
    print(parallelized)

在這種情況下,我得到25.0754394 ,因此使用多處理的開銷大於在單個內核中運行整個事物的執行時間。

    not_parallelized = timeit("""
result_df = f(df)
    """, 
    "from __main__ import pd, df, f", 
    number=5
    )
    print(not_parallelized)

然而,如果我們給f函數增加更多的復雜性,那么將df廣播到每個進程比在單個內核中運行它更便宜。

據我所知,pandas GroupBy:-Split,-Apply,-Combine可以解決您的問題。 將你的 DataFrame 分成多個塊(組),然后對每個塊(組)應用一個自定義函數 如果您有任何其他問題,我們可以討論代碼。

希望這可以幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM