pandas groupby apply не транслирует в фрейм данных

#python-3.x #pandas

#python-3.x #pandas

Вопрос:

Использование pandas 0.19.0. Следующий код воспроизведет проблему:

 In [1]: import pandas as pd
        import numpy as np

In [2]: df = pd.DataFrame({'c1' : list('AAABBBCCC'),
                           'c2' : list('abcdefghi'),
                           'c3' : np.random.randn(9),
                           'c4' : np.arange(9)})
        df
Out[2]:     c1  c2  c3          c4
        0   A   a   0.819618    0
        1   A   b   1.764327    1
        2   A   c   -0.539010   2
        3   B   d   1.430614    3
        4   B   e   -1.711859   4
        5   B   f   1.002522    5
        6   C   g   2.257341    6
        7   C   h   1.338807    7
        8   C   i   -0.458534   8

In [3]: def myfun(s):
            """Function does practically nothing"""
            req = s.values
            return pd.Series({'mean' : np.mean(req),
                              'std'  : np.std(req),
                              'foo'  : 'bar'})

In [4]: res = df.groupby(['c1', 'c2'])['c3'].apply(myfun)
        res.head(10)
Out[4]: c1  c2      
        A   a   foo          bar
                mean    0.819618
                std            0
            b   foo          bar
                mean     1.76433
                std            0
            c   foo          bar
                mean    -0.53901
                std            0
        B   d   foo          bar
  

И, конечно, я ожидаю этого:

 Out[4]:         foo  mean      std
        c1  c2     
        A   a   bar  0.819618  0
            b   bar  1.76433   0
            c   bar  -0.53901  0
        B   d   bar  1.43061   0 
  

Pandas автоматически преобразует серию в фрейм данных, когда возвращается функцией, которая применяется к ряду или фрейму данных. Почему поведение функций, применяемых к группам, отличается?

Я ищу ответ, который приведет к желаемому результату. Бонусные баллы за объяснение разницы в поведении между pandas.Series.apply or pandas.DataFrame.apply и pandas.core.groupby.GroupBy.apply

Комментарии:

1. Однако то, что вы пытаетесь сделать, принципиально отличается: вы возвращаете серию, а «столбцы», которые вы определяете в dict, станут индексом, поскольку эти значения индекса не существуют, он создает их как новый уровень индекса. Если вы сделали это: res = df.groupby(['c1', 'c2'])['c3'].apply(lambda x: pd.DataFrame({'mean' : [np.mean(x)], 'std' : [np.std(x)], 'foo' : 'bar'})) тогда это будет работать по желанию

2. @EdChum Спасибо Ed. Теперь я понял. Я был слишком сонным, чтобы увидеть это сам.

3. На самом деле, @EdChum я попытался вернуть фрейм данных, созданный с помощью того же словаря. Это тоже не сработало. Это то, что меня сбило с толку…

Ответ №1:

простым решением было бы unstack

 df = pd.DataFrame({'c1' : list('AAABBBCCC'),
                   'c2' : list('abcdefghi'),
                   'c3' : np.random.randn(9),
                   'c4' : np.arange(9)})

def myfun(s):
    """Function does practically nothing"""
    req = s.values
    return pd.Series({'mean' : np.mean(req),
                      'std'  : np.std(req),
                      'foo'  : 'bar'})

res = df.groupby(['c1', 'c2'])['c3'].apply(myfun)
res.unstack()
  

введите описание изображения здесь

Комментарии:

1. Да! Индекс интегрирован! Очевидно, что это уровень индекса. Мне нужно спать больше, чем 4 часа в сутки. Спасибо piRSquared, оценил.