Reputation: 31
I'm new to programming and Pandas, I'd like to have an example of how to apply a grouping function that also applies some counters to reduce the following DataFrame:
child | groupName | state |
---|---|---|
name1 | A | ok |
name2 | A | ko |
name3 | B | ok |
to a new DataFrame like:
groupName | noOfChildren | noOfOk | noOfKo |
---|---|---|---|
A | 2 | 1 | 1 |
B | 1 | 1 | 0 |
Given the allChildren DataFrame, I can create the Series counting the entries by groupName:
childrenByGroupName= allChildren.groupby(['groupName'])['name'].count();
And also the Series to filter them by 'ok' state:
okChildrenByGroupName= allChildren.where(['state']=='ok').groupby(['groupName'])['name'].count();
But I cannot build the merged DataFrame as per the above expectation. Any help?
Upvotes: 2
Views: 48
Reputation: 13349
you can try like this:
df1 = df.groupby(['groupName']).agg({'child': 'count', 'state': lambda x: x.value_counts().to_dict()}).add_prefix('noOf').reset_index()
df2 = pd.concat([df1.drop('noOfstate', axis=1), pd.DataFrame(df1['noOfstate'].tolist()).add_prefix('noOf')], axis=1).fillna(0)
df2:
groupName noOfchild noOfok noOfko
0 A 2 1 1.0
1 B 1 1 0.0
Upvotes: 2
Reputation: 150745
Try:
pd.crosstab(df['groupName'], df['state'], margins='sum')
Output:
state ko ok All
groupName
A 1 1 2
B 0 1 1
All 1 2 3
and to (almost) match the expected output:
(pd.crosstab(df['groupName'], df['state'], margins='sum', margins_name='Children')
.drop('Children')
.add_prefix('noOf')
.reset_index()
)
Upvotes: 3