Reputation: 4199
I am trying to group a dataframe with two columns and avoid default sorting using 'sort = False'. However, I am unable to achieve this.
Here is the simplified example
df = pd.DataFrame([
['zebra', 1, 10],
['zebra', 2, 10],
['apple', 3, 20],
['apple', 4, 20],
],
columns=['ColA','ColB','ColC'])
df is therefore
ColA ColB ColC
0 zebra 1 10
1 zebra 2 10
2 apple 3 20
3 apple 4 20
I am using pandas (1.0.3) groupby and disabling sorting of the keys
df_agg = df.groupby(by=['ColA','ColB'], sort = False)
df_agg.groups
results in
{('apple', 3): Int64Index([2], dtype='int64'),
('apple', 4): Int64Index([3], dtype='int64'),
('zebra', 1): Int64Index([0], dtype='int64'),
('zebra', 2): Int64Index([1], dtype='int64')}
which is the same as "sort = True" (default)
However, what I would like is as following
{
('zebra', 1): Int64Index([0], dtype='int64'),
('zebra', 2): Int64Index([1], dtype='int64'),
('apple', 3): Int64Index([2], dtype='int64'),
('apple', 4): Int64Index([3], dtype='int64')
}
'sort = False' when grouping by one column seems to be working fine.
df_agg = df.groupby(by=['ColA'], sort = False)
df_agg.groups
results in
{'zebra': Int64Index([0, 1], dtype='int64'),
'apple': Int64Index([2, 3], dtype='int64')}
If sorting only works on one column and not on tuples. I could sort the groups dict based on the tuple, but I am using an application that is expecting a groupby object. I appreciate any pointers on how this can be addressed.
Upvotes: 3
Views: 1536
Reputation: 294218
The groups
attribute is a dictionary and NOT where order of groups is determined. You must "resolve" the groupby
object with some operation to determine what the order is/was.
df.groupby(['ColA', 'ColB'], sort=False, as_index=False).first()
ColA ColB ColC
0 zebra 1 10
1 zebra 2 10
2 apple 3 20
3 apple 4 20
Versus
df.groupby(['ColA', 'ColB'], as_index=False).first()
ColA ColB ColC
0 apple 3 20
1 apple 4 20
2 zebra 1 10
3 zebra 2 10
The ACTUAL place to look is the groupby
object's ngroup
method
g1 = df.groupby(['ColA', 'ColB'], sort=False, as_index=False)
g1.ngroup()
0 0
1 1
2 2
3 3
dtype: int64
Versus
g2 = df.groupby(['ColA', 'ColB'], as_index=False)
g2.ngroup()
0 2
1 3
2 0
3 1
dtype: int64
Upvotes: 6
Reputation: 153460
Let's use a psuedo sort key, here I create one using pd.factorize
:
df.assign(sortkey=pd.factorize(df['ColA'])[0]).groupby(['sortkey', 'ColA', 'ColB']).groups
Output:
{(0, 'zebra', 1): Int64Index([0], dtype='int64'),
(0, 'zebra', 2): Int64Index([1], dtype='int64'),
(1, 'apple', 3): Int64Index([2], dtype='int64'),
(1, 'apple', 4): Int64Index([3], dtype='int64')}
Upvotes: 4