팬더 그룹 별 그룹으로 정렬


166

데이터 프레임을 두 개의 열로 그룹화 한 다음 그룹 내에서 집계 결과를 정렬하려고합니다.

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

이제 각 그룹 내에서 카운트 열을 내림차순으로 정렬하고 싶습니다. 그런 다음 상위 3 개 행만 가져갑니다. 다음과 같은 것을 얻으려면 :

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

답변:


147

당신이하고 싶은 것은 실제로 다시 groupby입니다 (첫 번째 groupby의 결과에 따라) : 그룹 당 처음 세 요소를 정렬하고 가져옵니다.

첫 번째 그룹의 결과부터 시작 :

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

인덱스의 첫 번째 수준으로 그룹화합니다.

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

그런 다음 각 그룹을 정렬 ( '순서')하고 처음 세 요소를 가져옵니다.

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

그러나이를 위해 다음과 같은 단축키 기능이 있습니다 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

그룹당 상위 3 개의 결과에 포함되지 않은 모든 것을 요약하여 각 작업에 대해 "other"라는 소스 그룹에 추가하는 방법이 있습니까?
JoeDanger

30
ordersort_values대신 사용되지 않습니다
zthomas.nc

큰 답변 주셔서 감사합니다. 추가 단계를 위해 groupby 열의 값을 기준으로 정렬 순서를 지정하는 방법이 있습니까? 예를 들어, 값이 '구매'이면 오름차순으로 정렬하고 값이 '판매'이면 내림차순으로 정렬하십시오.
보웬 리우

173

정렬을 먼저하고 head를 사용하여 각 그룹의 처음 3 개를 가져 와서 한 번에 수행 할 수도 있습니다.

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

14
groupby주문이 유지되도록 보장 합니까 ?
toto_tico

52
그것은 보인다; 에서 GROUPBY의 문서 : GROUPBY 각 그룹 내에서 행의 순서를 유지
toto_tico

10
toto_tico- 맞습니다. 그러나 그 문장을 해석 할 때는주의를 기울여야합니다. 단일 그룹 내의 행 순서는 유지되지만 groupby에는 기본적으로 sort = True 문이 있으므로 그룹 자체가 키에서 정렬되었을 수 있습니다. 즉, 내 데이터 프레임에 키 (입력시) 3 2 2 1이있는 경우 개체 별 그룹은 3 개의 그룹을 1 2 3 (정렬) 순서로 표시합니다. sort = False를 사용하여 그룹 순서와 행 순서를 유지하십시오.
user2103050

4
head (3)는 3 개 이상의 결과를 제공합니까?
Nabin

27

정렬 순서에서 상위 3 개를 가져오고 그룹 내에서 정렬하는 다른 예는 다음과 같습니다.

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

대신 이것을 시도하십시오

'groupby'를 수행하고 내림차순으로 정렬하는 간단한 방법

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

8

열을 합산 할 필요가 없으면 @tvashtar의 답변을 사용하십시오. 합산 해야하는 경우 @ joris '답변 또는 이와 매우 유사한 답변을 사용할 수 있습니다.

df.groupby(['job']).apply(lambda x: (x.groupby('source')
                                      .sum()
                                      .sort_values('count', ascending=False))
                                     .head(3))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.