Search code examples
pythonpandaspivot-tablesubtotal

Pivot table subtotals in Pandas


I have the following data:

Employee    Account Currency    Amount  Location
Test 2      Basic   USD         3000    Airport
Test 2      Net     USD         2000    Airport
Test 1      Basic   USD         4000    Town
Test 1      Net     USD         3000    Town
Test 3      Basic   GBP         5000    Town
Test 3      Net     GBP         4000    Town

I can manage to pivot by doing the following:

import pandas as pd
table = pd.pivot_table(df, values=['Amount'], index=['Location', 'Employee'], columns=['Account', 'Currency'], fill_value=0, aggfunc=np.sum, dropna=True)

Output:

                      Amount                  
Account            Basic         Net      
Currency             GBP   USD   GBP   USD
Location Employee                         
Airport  Test 2        0  3000     0  2000
Town     Test 1        0  4000     0  3000
         Test 3     5000     0  4000     0

How can I achieve subtotal by location and then a final grand total at the bottom. Desired output:

                  Amount                  
Account            Basic         Net      
Currency             GBP   USD   GBP   USD
Location Employee                         
Airport  Test 2        0  3000     0  2000
Airport  Total            3000     0  2000  
Town     Test 1        0  4000     0  3000
         Test 3     5000     0  4000     0
Town Total          5000  4000  4000  3000
Grand Total         5000  7000  4000  5000

I tried following the following. But it does not give the desired output. Thank you.


Solution

  • your pivot table

    table = pd.pivot_table(df, values=['Amount'],
                           index=['Location', 'Employee'],
                           columns=['Account', 'Currency'],
                           fill_value=0, aggfunc=np.sum, dropna=True, )
    print(table)
    
                      Amount                  
    Account            Basic         Net      
    Currency             GBP   USD   GBP   USD
    Location Employee                         
    Airport  Test 2        0  3000     0  2000
    Town     Test 1        0  4000     0  3000
             Test 3     5000     0  4000     0
    

    pandas.concat

    pd.concat([
        d.append(d.sum().rename((k, 'Total')))
        for k, d in table.groupby(level=0)
    ]).append(table.sum().rename(('Grand', 'Total')))
    
    
                      Amount                  
    Account            Basic         Net      
    Currency             GBP   USD   GBP   USD
    Location Employee                         
    Airport  2             0  3000     0  2000
             Total         0  3000     0  2000
    Town     1             0  4000     0  3000
             3          5000     0  4000     0
             Total      5000  4000  4000  3000
    Grand    Total      5000  7000  4000  5000
    

    Old Answer

    for posterity

    build sub totals

    tab_tots = table.groupby(level='Location').sum()
    tab_tots.index = [tab_tots.index, ['Total'] * len(tab_tots)]
    print(tab_tots)
    
                   Amount                  
    Account         Basic         Net      
    Currency          GBP   USD   GBP   USD
    Location                               
    Airport  Total      0  3000     0  2000
    Town     Total   5000  4000  4000  3000
    

    all together

    pd.concat(
        [table, tab_tots]
    ).sort_index().append(
        table.sum().rename(('Grand', 'Total'))
    )
    

    enter image description here