Python pandas groupby globale sur plusieurs colonnes, puis faites pivoter

en Python, j'ai une DataFrame de pandas similaire à la suivante:

Item | shop1 | shop2 | shop3 | Category
------------------------------------
Shoes| 45    | 50    | 53    | Clothes
TV   | 200   | 300   | 250   | Technology
Book | 20    | 17    | 21    | Books
phone| 300   | 350   | 400   | Technology
<!-Où shop1, shop2 et shop3 sont les coûts de chaque article dans les différents magasins. Maintenant, je dois retourner une DataFrame, après quelques nettoyages de données, comme celle-ci:

Category (index)| size| sum| mean | std
----------------------------------------

où la taille est le nombre d'articles dans chaque catégorie et la somme, la moyenne et la MST sont liées aux mêmes fonctions appliquées aux 3 ateliers. Comment puis-je effectuer ces opérations avec le split-appliquer-combiner motif (groupby, agréger, appliquer,...) ?

quelqu'un Peut-il m'aider? Je deviens folle avec celui-là...je vous remercie!

12
demandé sur smci 2017-04-02 23:03:44

3 réponses

édité pour Pandas 0.22+ considérant la dévalorisation de l'utilisation des dictionnaires dans un groupe par agrégation.

nous avons mis en place un dictionnaire très similaire où nous utilisons les touches du dictionnaire pour spécifier nos fonctions et le dictionnaire lui-même pour renommer les colonnes.

rnm_cols = dict(size='Size', sum='Sum', mean='Mean', std='Std')
df.set_index(['Category', 'Item']).stack().groupby('Category') \
  .agg(rnm_cols.keys()).rename(columns=rnm_cols)

            Size   Sum        Mean        Std
Category                                     
Books          3    58   19.333333   2.081666
Clothes        3   148   49.333333   4.041452
Technology     6  1800  300.000000  70.710678

option 1

utiliser agg ← lien docs

agg_funcs = dict(Size='size', Sum='sum', Mean='mean', Std='std')
df.set_index(['Category', 'Item']).stack().groupby(level=0).agg(agg_funcs)

                  Std   Sum        Mean  Size
Category                                     
Books        2.081666    58   19.333333     3
Clothes      4.041452   148   49.333333     3
Technology  70.710678  1800  300.000000     6

option 2

plus pour moins

utiliser describe ← lien vers docs

df.set_index(['Category', 'Item']).stack().groupby(level=0).describe().unstack()

            count        mean        std    min    25%    50%    75%    max
Category                                                                   
Books         3.0   19.333333   2.081666   17.0   18.5   20.0   20.5   21.0
Clothes       3.0   49.333333   4.041452   45.0   47.5   50.0   51.5   53.0
Technology    6.0  300.000000  70.710678  200.0  262.5  300.0  337.5  400.0
13
répondu piRSquared 2018-03-21 22:47:51
df.groupby('Category').agg({'Item':'size','shop1':['sum','mean','std'],'shop2':['sum','mean','std'],'shop3':['sum','mean','std']})

Ou si vous le souhaitez dans tous les magasins alors:

df1 = df.set_index(['Item','Category']).stack().reset_index().rename(columns={'level_2':'Shops',0:'costs'})
df1.groupby('Category').agg({'Item':'size','costs':['sum','mean','std']})
5
répondu Scott Boston 2017-04-02 23:22:27

si je comprends bien, vous voulez calculer des mesures agrégées pour tous les magasins, pas pour chacun individuellement. Pour ce faire, vous pouvez d'abord stack votre dataframe et puis groupez par Category:

stacked = df.set_index(['Item', 'Category']).stack().reset_index()
stacked.columns = ['Item', 'Category', 'Shop', 'Price']
stacked.groupby('Category').agg({'Price':['count','sum','mean','std']})

résultats

           Price                             
           count   sum        mean        std
Category                                     
Books          3    58   19.333333   2.081666
Clothes        3   148   49.333333   4.041452
Technology     6  1800  300.000000  70.710678
0
répondu foglerit 2017-04-02 20:40:58