Q:

Mixing aggregation and group by in pandas

What I have is a data set called 'report' which has details of delivery drivers.  'Pass' means they delivered on time and 'Fail' means they didn't
Name|Outcome
A   |Pass
B   |Fail
C   |Pass
D   |Pass
A   |Fail
C   |Pass

What I want
Name|Pass|Fail|Total
A   |1   |1   |2
B   |0   |1   |1
C   |2   |0   |2
D   |1   |0   |1

I tried:      
report.groupby(['Name','outcome']).agg(['count'])

but it is not giving me the required output
Many Thanks

A:

Use crosstab with margins=True and margins_name parameter:
print (pd.crosstab(df['Name'], df['Outcome'], margins=True, margins_name='Total'))
Outcome  Fail  Pass  Total
Name                      
A           1     1      2
B           1     0      1
C           0     2      2
D           0     1      1
Total       2     4      6

And then remove last row with positions by DataFrame.iloc:
df = pd.crosstab(df['Name'], df['Outcome'], margins=True, margins_name='Total').iloc[:-1]
print (df)
Outcome  Fail  Pass  Total
Name                      
A           1     1      2
B           1     0      1
C           0     2      2
D           0     1      1

A:

This is pd.crosstab with sum over axis=1:
df = pd.crosstab(df['Name'], df['Outcome'])
df['Total'] = df[['Fail', 'Pass']].sum(axis=1)

Outcome  Fail  Pass  Total
Name                      
A           1     1      2
B           1     0      1
C           0     2      2
D           0     1      1

Or to remove the column axis name, we use rename_axis:
df = pd.crosstab(df['Name'], df['Outcome']).reset_index().rename_axis(None, axis='columns')
df['Total'] = df[['Fail', 'Pass']].sum(axis=1)

  Name  Fail  Pass  Total
0    A     1     1      2
1    B     1     0      1
2    C     0     2      2
3    D     0     1      1

