グループの順序を変更せずにグループ内で並べ替えますか?

Aug 21 2020

このオンラインで最新の回答を見つけることができないようです。私が抱えている問題は、基本的にこの質問と同じです。つまり、データセットrevenuegroupの順序を変更せずに、内で並べ替えたいということですgroup

そのスレッドへの答えは間違っています。それは、たまたま反アルファベット順に並べられた例に2つのグループしかなかったためにのみ機能します。

しようとするとdf.groupby('group').sort_values('revenue')、エラーが発生します'DataFrameGroupBy' object has no attribute 'sort_values'

これどうやってするの?

サンプルDataFrame:

    name    group   revenue
0   Name1   GroupB  1
3   Name4   GroupA  4
4   Name5   GroupA  5
8   Name7   GroupC  9
1   Name2   GroupB  2
2   Name3   GroupB  3
5   Name6   GroupA  6
6   Name7   GroupC  7
7   Name7   GroupC  8

期待される出力:

    name   group  revenue
2  Name3  GroupB        3
1  Name2  GroupB        2
0  Name1  GroupB        1
5  Name6  GroupA        6
4  Name5  GroupA        5
3  Name4  GroupA        4
8  Name7  GroupC        9
7  Name7  GroupC        8
6  Name7  GroupC        7

回答

2 DavidErickson Aug 22 2020 at 00:50

あなたは、変換した新しい一時的な列を作成することができBAおよびC12そして3あなたが順不同の秩序を維持するようにすることを、。次に、一時的な列を削除します。回答#1では、これはより動的であり、group列の値が連続してグループ化されていない場合に機能します。回答#2の場合、それらは連続している必要があります(回答#1と回答#2の入力の順序が異なります)

更新された回答#1(コメントごと-グループは行で連続していませんが、各グループ内の最初の値の出現順に正しく並べたいと思います。)コード[l for l in enumerate((df['group'].unique()))]は、各グループに応じて番号を割り当てます。groupデータフレーム内の列の最初の値の順序。

In[1]:
    name    group   revenue
0   Name1   GroupB  1
3   Name4   GroupA  4
4   Name5   GroupA  5
8   Name7   GroupC  9
1   Name2   GroupB  2
2   Name3   GroupB  3
5   Name6   GroupA  6
6   Name7   GroupC  7
7   Name7   GroupC  8

dft = pd.DataFrame([l for l  in enumerate((df['group'].unique()))], columns=['group_number','group'])
df = pd.merge(df, dft, how='left', on='group').sort_values(['group_number', 'revenue'], ascending = [True, False])
df

Out[1]: 
    name   group  revenue  group_number
5  Name3  GroupB        3             0
4  Name2  GroupB        2             0
0  Name1  GroupB        1             0
6  Name6  GroupA        6             1
2  Name5  GroupA        5             1
1  Name4  GroupA        4             1
3  Name7  GroupC        9             2
8  Name7  GroupC        8             2
7  Name7  GroupC        7             2

私はの出力ハイライトしたかったdftenumerateマージソートの前にコードの行を。

dft = pd.DataFrame([l for l  in enumerate((df['group'].unique()))], columns=['group_number','group'])
dft

Out[2]: 
   group_number   group
0             0  GroupB
1             1  GroupA
2             2  GroupC

回答#2

import pandas as pd
df = pd.DataFrame({'name': ['Name1','Name2','Name3','Name4','Name5','Name6', 'Name7', 'Name7', 'Name7'], 
    'group':['GroupB','GroupB','GroupB','GroupA','GroupA','GroupA','GroupC','GroupC','GroupC'],'revenue':[1,2,3,4,5,6,7,8,9]})
df['cs'] = (df['group'] != df['group'].shift(1)).cumsum()
df = df.sort_values(['cs', 'revenue'], ascending = [True, False])
df
Out[11]: 
    name   group  revenue  cs
2  Name3  GroupB        3   1
1  Name2  GroupB        2   1
0  Name1  GroupB        1   1
5  Name6  GroupA        6   2
4  Name5  GroupA        5   2
3  Name4  GroupA        4   2
8  Name7  GroupC        9   3
7  Name7  GroupC        8   3
6  Name7  GroupC        7   3

両方の回答について、列をドロップするだけです。

df = df.drop('cs', axis=1)

Out[12]: 
    name   group  revenue
2  Name3  GroupB        3
1  Name2  GroupB        2
0  Name1  GroupB        1
5  Name6  GroupA        6
4  Name5  GroupA        5
3  Name4  GroupA        4
8  Name7  GroupC        9
7  Name7  GroupC        8
6  Name7  GroupC        7
quizzical_panini Aug 21 2020 at 23:58

なぜgroupbyを使用するのですか?複数のsort_values呼び出しをチェーンして、正しいソート順を取得することができます。たとえば、リンクされた質問と同様のデータを使用し、収益の降順で並べ替えたいが、グループを昇順で維持したい場合は、次のようにします。

import pandas as pd

df = pd.DataFrame({'name': ['Name1','Name2','Name3','Name4','Name5','Name6', 'Name7', 'Name7', 'Name7'], 
    'group':['GroupB','GroupB','GroupB','GroupA','GroupA','GroupA','GroupC','GroupC','GroupC'],'revenue':[1,2,3,4,5,6,7,8,9]})

df.sort_values(by='revenue', ascending= False).sort_values(by='group')

どちらが返されますか:

name    group   revenue
5   Name6   GroupA  6
4   Name5   GroupA  5
3   Name4   GroupA  4
2   Name3   GroupB  3
1   Name2   GroupB  2
0   Name1   GroupB  1
8   Name7   GroupC  9
7   Name7   GroupC  8
6   Name7   GroupC  7