Pandas Date Groupby & Apply - улучшение производительности - PullRequest
3 голосов
/ 18 апреля 2019

Я делаю полчаса по группам дат и применяюсь для расчета ежедневной статистики по моему набору данных, но это медленно. Есть ли способ улучшить производительность следующих функций? Я читал о векторизации, но не уверен, как ее реализовать.

Я использовал apply и transform для получения желаемых результатов, но для данных за целый год требуется около 2-3 секунд, я надеюсь сделать это быстрее, так как у меня много данных. Кто-нибудь может указать мне правильное направление?

import pandas as pd
import numpy as np
import timeit

# dummy data
date_range = pd.date_range('2017-01-01 00:00', '2018-01-01 00:00', freq='30Min')
df = pd.DataFrame(np.random.randint(2, 20, (date_range.shape[0], 2)), index=date_range, columns=['Electricity', 'Natural Gas'])

print(df.head())
print(df.shape)

t1 = timeit.default_timer()
onhour = df.groupby([pd.Grouper(freq='D')]).apply(lambda x: np.count_nonzero(
    x[x > x.quantile(0.05) + x.mean() * .1] >
    x.quantile(0.05) + 0.25 * (x.quantile(0.95)-x.quantile(0.05)),
    axis=0) / 2)

onhour = pd.DataFrame(
    onhour.values.tolist(),
    index=onhour.index,
    columns=df.columns)

print(f"start_time in {timeit.default_timer() - t1}")
print(onhour.head())

t1 = timeit.default_timer()
onhour = df.groupby([pd.Grouper(freq='D')]).transform(lambda x: np.count_nonzero(
    x[x > x.quantile(0.05) + x.mean() * .1] >
    x.quantile(0.05) + 0.25 * (x.quantile(0.95)-x.quantile(0.05)),
    axis=0) / 2).resample('D').mean()

print(f"start_time in {timeit.default_timer() - t1}")
print(onhour.head())

1 Ответ

2 голосов
/ 18 апреля 2019

Вы уже используете оптимизацию векторизации панд, так что вы не можете выиграть много времени, но несколько трюков помогут вам за 1,5 секунды.

1) Используйте agg

Использование agg вместо transform или apply даст лучший результат, потому что у вас одинаковые вычисления для каждого столбца (электричество и газ) .

2) сохраните вычисления квантилей.

Вы рассчитываете в 3 раза больше 5% квантиля.Я использовал python function вместо lambda, вы все равно могли бы использовать лямбду, если добавляете запомненную функцию квантиля (она может действительно помочь закрепить, но я уверен).

def count_something(row):
    qt_df = row.quantile([0.05, 0.95])
    return np.count_nonzero(
        row[row > qt_df.loc[0.05] + row.mean() * .1] > qt_df.loc[0.05] + 0.25 * (qt_df.loc[0.95] - qt_df.loc[0.05]),
        axis=0) / 2

t1 = timeit.default_timer()

onhour = df.groupby([pd.Grouper(freq='D')]).agg(count_something)

print(f"start_time in {timeit.default_timer() - t1}")
print(onhour.head())

Если вы действительноЕсли вы хотите ускорить вычисления, и у вас есть способы упорядочить или распространить ваши вычисления, я думаю, вы могли бы использовать python dask , но я не думаю, насколько это может улучшить вашу проблему.

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