Панды, как использовать pivot_table для агрегирования данных для средних значений - PullRequest
0 голосов
/ 12 декабря 2018

У меня есть следующие значения df,

code    post_date    inv_date     year_month
750     2017-12-11   2017-11-29   201711
750     2017-12-12   2017-11-30   201711
750     2017-12-13   2017-12-01   201712
750     2017-12-14   2017-12-02   201712
750     2017-12-15   2017-12-03   201712
760     2017-12-16   2017-12-04   201711
760     2017-12-05   2017-12-05   201711
760     2017-12-28   2017-12-16   201711
760     2017-12-29   2017-12-17   201712
760     2017-12-30   2017-12-18   201712

Сначала я groupby code и year_month,

df_grp_by = df.groupby(['code', 'year_month'])

, а затем вычисляю среднее число днейpost_date - inv_date в каждой группе,

df_avg_proc_days = df_grp_by.apply(lambda row: (row['post_date'] -row['inv_date']).dt.days).mean(level=[0, 1]).reset_index(name='avg_days')

Я хотел бы получить новый df сверху, выглядит следующим образом:

      0    1       2         3
0    -1    0    201711    201712
1     0    10.8   9.6       12
2    750   12     12        12
3    760   9.6     8        12

-1 являетсяфиктивное значение для поддержания формы матрицы;0 представляет «все» значения, которые усредняют значения code или year_month или code и year_month, например, ячейка (1,1) составляет в среднем post_date - inv_date для всех строк в df;(1,2) в среднем post_date - inv_date для 201711 во всех строках, которые имеют это значение для year_month в df.

Я попытался использовать следующий код для генерации матрицы,

def convert_to_matrix(df, p_tab_idx, p_tab_cols, p_tab_vals, p_tab_agg_func, fill_na=-1):
    df_tab = (df.pivot_table(index=p_tab_idx,
                         columns=p_tab_cols,
                         values=p_tab_vals,
                         margins=True,
                         aggfunc=p_tab_agg_func,
                         fill_value=fill_na,
                         margins_name='0'))

    # change order of index and columns values for reindex
    idx = df_tab.index[-1:].tolist() + df_tab.index[:-1].tolist()
    cols = df_tab.columns[-1:].tolist() + df_tab.columns[:-1].tolist()

    df_tab = (df_tab.reindex(index=idx, columns=cols)
          .reset_index()
          .rename(columns={p_tab_idx: -1})
          .rename_axis(None, 1))

    # add columns to first row
    df_tab = df_tab.columns.to_frame().T.append(df_tab).reset_index(drop=True)
    # reset columns names to range
    df_tab.columns = range(len(df_tab.columns))
    # converts column labels from int to str
    df_tab.columns = df_tab.columns.astype(str)

    return df_tab

df_p_tab = convert_to_matrix(df_avg_proc_days, 
                             p_tab_idx='code', 
                             p_tab_cols='year_month', 
                             p_tab_vals='avg_days', 
                             p_tab_agg_func='mean')

но это генерирует,

     0   1       2       3
0   -1   0  201711  201712
1    0  11      10      12
2  750  12      12      12
3  760  10       8      12

Мне интересно, как это исправить.

...