I have this dataframe
x = pd.DataFrame.from_dict({'cat1':['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C'], 'cat2':['X', 'X', 'Y', 'Y', 'Y', 'Y', 'Z', 'Z']})
cat1 cat2
0 A X
1 A X
2 A Y
3 B Y
4 B Y
5 C Y
6 C Z
7 C Z
I want to group by cat1
, and then aggregate cat2
as sets of different values, such as
cat1 cat2
0 A (X, Y)
1 B (Y,)
2 C (Y, Z)
This is part of a bigger dataframe with more columns, each of which has its own aggregation function, so how do I pass this functionality to the aggregation dictionary?
Use lambda function with set
or unique
, also convert output to tuple
s:
x = pd.DataFrame.from_dict({'cat1':['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C'],
'cat2':['X', 'X', 'Y', 'Y', 'Y', 'Y', 'Z', 'Z'],
'col':range(8)})
print (x)
cat1 cat2 col
0 A X 0
1 A X 1
2 A Y 2
3 B Y 3
4 B Y 4
5 C Y 5
6 C Z 6
7 C Z 7
a = x.groupby('cat1').agg({'cat2': lambda x: tuple(set(x)), 'col':'sum'})
print (a)
cat2 col
cat1
A (Y, X) 3
B (Y,) 7
C (Y, Z) 18
Or:
a = x.groupby('cat1').agg({'cat2': lambda x: tuple(x.unique()), 'col':'sum'})
print (a)
cat2 col
cat1
A (X, Y) 3
B (Y,) 7
C (Y, Z) 18
EDIT:
f = lambda x: tuple(x.unique())
f.__name__ = 'my_name'
a = x.groupby('cat1')['cat2'].agg(['min', 'max', 'nunique', f])
print (a)
min max nunique my_name
cat1
A X Y 2 (X, Y)
B Y Y 1 (Y,)
C Y Z 2 (Y, Z)
If there is only one lambda
function or no problem with column name <lambda>
:
a = x.groupby('cat1')['cat2'].agg(['min', 'max', 'nunique', lambda x: tuple(x.unique())])
print (a)
min max nunique <lambda>
cat1
A X Y 2 (X, Y)
B Y Y 1 (Y,)
C Y Z 2 (Y, Z)
Groupby and unique gives you unique values
x.groupby('cat1').cat2.unique()
A [X, Y]
B [Y]
C [Y, Z]
If you want to have the output in tuple, try
x.groupby('cat1').cat2.unique().apply(tuple)
A (X, Y)
B (Y,)
C (Y, Z)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With