Pandas Dataframe groupby описывает в 8 раз медленнее, чем вычисление отдельно - PullRequest
0 голосов
/ 25 июня 2018

Следующий код суммирует числовые данные с использованием двух разных подходов.

Первый подход использует Dataframe (). Description () и пропускает некоторые дополнительные процентили.

* Второй подход отдельно вычисляет итоговую статистику (среднее, стандартное, N), суммирует ее, вычисляет те же квантили, затем добавляет два и сортирует по индексу, так что результат по существу такой же, как и в первомподход.

Существуют некоторые незначительные различия в именах, которые мы можем устранить после слов, и поскольку суммарные данные невелики, это очень быстро.

Оказывается, что использование функции описания было примерно в 8 раз медленнеепример.

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

import pandas as pd
import numpy as np
from datetime import datetime

def make_data (n):

    ts = datetime.now().timestamp() + abs(np.random.normal(60, 30, n)).cumsum()

    df = pd.DataFrame({
        'c1': np.random.choice(list('ABCDEFGH'), n),
        'c2': np.random.choice(list('ABCDEFGH'), n),
        'c3': np.random.choice(list('ABCDEFGH'), n),
        't1': np.random.randint(1, 20, n),
        't2': pd.to_datetime(ts, unit='s'),
        'x1': np.random.randn(n),
        'x2': np.random.randn(n),
        'x3': np.random.randn(n)
        })

    return df

def summarize_numeric_1 (df, mask, groups, values, quantiles): 

    dfg = df[mask].groupby(groups)[values]

    return dfg.describe(percentiles = quantiles).stack()

def summarize_numeric_2 (df, filt, groups, values, quantiles): 

    dfg = df[mask].groupby(groups)[values]

    dfg_stats = dfg.agg([np.mean, np.std, len]).stack()
    dfg_quantiles = dfg.quantile(all_quantiles)

    return dfg_stats.append(dfg_quantiles).sort_index()

%time df = make_data(1000000)

groups = ['c1', 'c2', 't1']
mask = df['c3'].eq('H') & df['c1'].eq('A')
values = ['x1', 'x3']
base_quantiles = [0, .5, 1] 
extd_quantiles = [0.25, 0.75, 0.9]
all_quantiles = base_quantiles + extd_quantiles

%timeit summarize_numeric_1(df, mask, groups, values, extd_quantiles)
%timeit summarize_numeric_2(df, mask, groups, values, all_quantiles)

Время на моем ПК для этого:

Использование описания: 873 мс ±8,9 мс на цикл (среднее ± стандартное отклонение из 7 циклов, по 1 циклу каждый)

Использование двухэтапного метода: 105 мс ± 490 мкс на цикл (среднее ± стандартное отклонение из 7 циклов, 10 цикловкаждый)

Все входы приветствуются!

...