Распараллеливание операций для pandas кадра данных - PullRequest
0 голосов
/ 15 марта 2020

У меня есть очень большой pandas фрейм данных, подобный следующему:

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

(Есть несколько столбцов, необходимых для выполнения некоторых вычислений)

Итак, для каждого клиента у меня есть применять множество операций (сдвиг, суммы, вычитания, условия и т. д. c), поэтому невозможно (на мой взгляд) применить логическое маскирование для всего, я уже пробовал, поэтому мой вопрос заключается в том, можно ли разделить 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_...    ║    ... ║
╚════════╩═════════════╩════════╝

И применяет все операции также ко всем этим чанкам параллельно.

Ответы [ 2 ]

2 голосов
/ 15 марта 2020

Вы можете использовать многопроцессорный пул для выполнения sh некоторых из этих задач, однако многопроцессорная обработка также является дорогостоящей операцией, поэтому вам необходимо проверить, действительно ли распараллеливание происходит быстрее, это зависит от типа выполняемых вами функций. и данные, например, я создаю образец 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 в моем старом ноутбуке:

    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 каждому процессу обходится дешевле, чем ее запуск в одном ядре.

0 голосов
/ 15 марта 2020

Насколько мне известно, pandas GroupBy: -Split, -Apply, -Combine может решить вашу проблему. Разделите ваш DataFrame на несколько блоков (групп), а затем примените самоопределенную функцию к каждому блоку (группе). Мы можем говорить коды, если у вас есть какие-либо вопросы.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...