Pandas tableaux croisés dynamiques sous totaux de ligne

J'utilise Pandas 0.10.1

Considérant ce Dataframe:

Date       State   City    SalesToday  SalesMTD  SalesYTD
20130320     stA    ctA            20       400      1000
20130320     stA    ctB            30       500      1100
20130320     stB    ctC            10       500       900
20130320     stB    ctD            40       200      1300
20130320     stC    ctF            30       300       800

Comment puis-je regrouper les sous-totaux par état?

State   City  SalesToday  SalesMTD  SalesYTD
  stA    ALL          50       900      2100
  stA    ctA          20       400      1000
  stA    ctB          30       500      1100

J'ai essayé avec un tableau croisé dynamique mais je ne peux avoir que des sous-totaux dans les colonnes

table = pivot_table(df, values=['SalesToday', 'SalesMTD','SalesYTD'],
                     rows=['State','City'], aggfunc=np.sum, margins=True)

Je peux y parvenir sur excel, avec un tableau croisé dynamique.

34
demandé sur balsagoth 2013-03-22 16:16:10

4 réponses

Si vous mettez State et City pas les deux dans les lignes, vous obtiendrez des marges séparées. Remodeler et vous obtenez la table que vous recherchez:

In [10]: table = pivot_table(df, values=['SalesToday', 'SalesMTD','SalesYTD'],\
                     rows=['State'], cols=['City'], aggfunc=np.sum, margins=True)


In [11]: table.stack('City')
Out[11]: 
            SalesMTD  SalesToday  SalesYTD
State City                                
stA   All        900          50      2100
      ctA        400          20      1000
      ctB        500          30      1100
stB   All        700          50      2200
      ctC        500          10       900
      ctD        200          40      1300
stC   All        300          30       800
      ctF        300          30       800
All   All       1900         130      5100
      ctA        400          20      1000
      ctB        500          30      1100
      ctC        500          10       900
      ctD        200          40      1300
      ctF        300          30       800

J'admets que ce n'est pas totalement évident.

39
répondu Wes McKinney 2013-03-22 16:07:31

Vous pouvez obtenir les valeurs résumées en utilisant groupby () sur la colonne State.

Permet de faire quelques exemples de données en premier:

import pandas as pd
import StringIO

incsv = StringIO.StringIO("""Date,State,City,SalesToday,SalesMTD,SalesYTD
20130320,stA,ctA,20,400,1000
20130320,stA,ctB,30,500,1100
20130320,stB,ctC,10,500,900
20130320,stB,ctD,40,200,1300
20130320,stC,ctF,30,300,800""")

df = pd.read_csv(incsv, index_col=['Date'], parse_dates=True)

Ensuite, appliquez la fonction groupby et ajoutez une ville de colonne:

dfsum = df.groupby('State', as_index=False).sum()
dfsum['City'] = 'All'

print dfsum

  State  SalesToday  SalesMTD  SalesYTD City
0   stA          50       900      2100  All
1   stB          50       700      2200  All
2   stC          30       300       800  All

Nous pouvons ajouter les données d'origine à la somme DF en utilisant append:

dfsum.append(df).set_index(['State','City']).sort_index()

print dfsum

            SalesMTD  SalesToday  SalesYTD
State City                                
stA   All        900          50      2100
      ctA        400          20      1000
      ctB        500          30      1100
stB   All        700          50      2200
      ctC        500          10       900
      ctD        200          40      1300
stC   All        300          30       800
      ctF        300          30       800

J'ai ajouté set_index et sort_index pour le faire ressembler davantage à votre exemple de sortie, ce n'est pas strictement nécessaire pour obtenir les résultats.

19
répondu Rutger Kassies 2013-03-22 12:38:30

Je pense que ce code d'exemple de sous-total est ce que vous voulez (similaire à Excel subtotal)

Je suppose que vous voulez grouper par les colonnes A, B, C, D, que compter la valeur de la colonne de E

main_df.groupby(['A', 'B', 'C']).apply(lambda sub_df: sub_df\
       .pivot_table(index=['D'], values=['E'], aggfunc='count', margins=True)

Sortie:

A B C  D  E
       a  1 
a a a  b  2
       c  2
     all  5
       a  3 
b b a  b  2
       c  2
     all  7
       a  3 
b b b  b  6
       c  2
       d  3
     all 14
4
répondu hs moon 2017-04-20 21:49:50

Et celui-ci ?

table = pd.pivot_table(data, index=['State'],columns = ['City'],values=['SalesToday', 'SalesMTD','SalesYTD'],\
                      aggfunc=np.sum, margins=True)

entrez la description de l'image ici

0
répondu Richard Mao 2016-05-13 05:43:54