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.
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.
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.
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
Et celui-ci ?
table = pd.pivot_table(data, index=['State'],columns = ['City'],values=['SalesToday', 'SalesMTD','SalesYTD'],\
aggfunc=np.sum, margins=True)