gấu trúc nhóm sắp xếp trong nhóm


166

Tôi muốn nhóm khung dữ liệu của mình theo hai cột và sau đó sắp xếp các kết quả tổng hợp trong các nhóm.

In [167]:
df

Out[167]:
count   job source
0   2   sales   A
1   4   sales   B
2   6   sales   C
3   3   sales   D
4   7   sales   E
5   5   market  A
6   3   market  B
7   2   market  C
8   4   market  D
9   1   market  E

In [168]:
df.groupby(['job','source']).agg({'count':sum})

Out[168]:
            count
job     source  
market  A   5
        B   3
        C   2
        D   4
        E   1
sales   A   2
        B   4
        C   6
        D   3
        E   7

Bây giờ tôi muốn sắp xếp cột đếm theo thứ tự giảm dần trong mỗi nhóm. Và sau đó chỉ mất ba hàng đầu. Để có được một cái gì đó như:

            count
job     source  
market  A   5
        D   4
        B   3
sales   E   7
        C   6
        B   4

Câu trả lời:


147

Những gì bạn muốn làm thực sự lại là một nhóm (trên kết quả của nhóm đầu tiên): sắp xếp và lấy ba yếu tố đầu tiên cho mỗi nhóm.

Bắt đầu từ kết quả của nhóm đầu tiên:

In [60]: df_agg = df.groupby(['job','source']).agg({'count':sum})

Chúng tôi nhóm theo cấp độ đầu tiên của chỉ số:

In [63]: g = df_agg['count'].groupby(level=0, group_keys=False)

Sau đó, chúng tôi muốn sắp xếp ('thứ tự') mỗi nhóm và lấy ba yếu tố đầu tiên:

In [64]: res = g.apply(lambda x: x.order(ascending=False).head(3))

Tuy nhiên, đối với điều này, có một chức năng phím tắt để làm điều này , nlargest:

In [65]: g.nlargest(3)
Out[65]:
job     source
market  A         5
        D         4
        B         3
sales   E         7
        C         6
        B         4
dtype: int64

Có cách nào để tổng hợp tất cả mọi thứ không có trong ba kết quả hàng đầu cho mỗi nhóm và thêm chúng vào một nhóm nguồn gọi là "khác" cho mỗi công việc không?
JoeDanger

30
orderkhông được sử dụng sort_valuesthay thế
zthomas.nc

Cảm ơn câu trả lời tuyệt vời. Đối với một bước nữa, sẽ có cách nào để gán thứ tự sắp xếp dựa trên các giá trị trong cột nhóm? Chẳng hạn, sắp xếp tăng dần nếu giá trị là 'Mua' và sắp xếp giảm dần nếu giá trị là 'Bán'.
Bowen Liu

171

Bạn cũng có thể chỉ cần thực hiện trong một lần, bằng cách thực hiện sắp xếp trước và sử dụng đầu để lấy 3 đầu tiên của mỗi nhóm.

In[34]: df.sort_values(['job','count'],ascending=False).groupby('job').head(3)

Out[35]: 
   count     job source
4      7   sales      E
2      6   sales      C
1      4   sales      B
5      5  market      A
8      4  market      D
6      3  market      B

13
groupbyđảm bảo rằng trật tự được bảo tồn?
toto_tico

51
Có vẻ như nó làm; từ tài liệu của groupby : groupby duy trì thứ tự các hàng trong mỗi nhóm
toto_tico

10
toto_tico- Điều đó là chính xác, tuy nhiên cần phải cẩn thận khi diễn giải câu nói đó. Thứ tự của các hàng TRONG MỘT NHÓM SINGLE được giữ nguyên, tuy nhiên, nhóm có một câu lệnh sort = True theo mặc định, có nghĩa là các nhóm có thể đã được sắp xếp trên khóa. Nói cách khác, nếu khung dữ liệu của tôi có các khóa (trên đầu vào) 3 2 2 1, .. nhóm theo đối tượng sẽ hiển thị 3 nhóm theo thứ tự 1 2 3 (được sắp xếp). Sử dụng sort = false để đảm bảo trật tự nhóm và thứ tự hàng được giữ nguyên.
user2103050

4
đầu (3) cho nhiều hơn 3 kết quả?
Nabin

27

Đây là ví dụ khác về việc đứng đầu 3 về thứ tự được sắp xếp và sắp xếp trong các nhóm:

In [43]: import pandas as pd                                                                                                                                                       

In [44]:  df = pd.DataFrame({"name":["Foo", "Foo", "Baar", "Foo", "Baar", "Foo", "Baar", "Baar"], "count_1":[5,10,12,15,20,25,30,35], "count_2" :[100,150,100,25,250,300,400,500]})

In [45]: df                                                                                                                                                                        
Out[45]: 
   count_1  count_2  name
0        5      100   Foo
1       10      150   Foo
2       12      100  Baar
3       15       25   Foo
4       20      250  Baar
5       25      300   Foo
6       30      400  Baar
7       35      500  Baar


### Top 3 on sorted order:
In [46]: df.groupby(["name"])["count_1"].nlargest(3)                                                                                                                               
Out[46]: 
name   
Baar  7    35
      6    30
      4    20
Foo   5    25
      3    15
      1    10
dtype: int64


### Sorting within groups based on column "count_1":
In [48]: df.groupby(["name"]).apply(lambda x: x.sort_values(["count_1"], ascending = False)).reset_index(drop=True)
Out[48]: 
   count_1  count_2  name
0       35      500  Baar
1       30      400  Baar
2       20      250  Baar
3       12      100  Baar
4       25      300   Foo
5       15       25   Foo
6       10      150   Foo
7        5      100   Foo

9

Thay vào đó hãy thử

cách đơn giản để làm 'nhóm' và sắp xếp theo thứ tự giảm dần

df.groupby(['companyName'])['overallRating'].sum().sort_values(ascending=False).head(20)

8

Nếu bạn không cần tổng hợp một cột, thì hãy sử dụng câu trả lời của @ tvashtar. Nếu bạn cần tổng hợp, thì bạn có thể sử dụng câu trả lời của @joris hoặc câu trả lời này rất giống với câu trả lời.

df.groupby(['job']).apply(lambda x: (x.groupby('source')
                                      .sum()
                                      .sort_values('count', ascending=False))
                                     .head(3))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.