티스토리 뷰

반응형

Stack Overflow에 자주 검색, 등록되는 문제들과 제가 개발 중 찾아 본 문제들 중에서 나중에도 찾아 볼 것 같은 문제들을 정리하고 있습니다.

Stack Overflow에서 가장 먼저 확인하게 되는 가장 높은 점수를 받은 Solution과 현 시점에 도움이 될 수 있는 가장 최근에 업데이트(최소 점수 확보)된 Solution을 각각 정리하였습니다.

 

아래 word cloud를 통해 이번 포스팅의 주요 키워드를 미리 확인하세요.

Get the row(s) which have the max value in groups using groupby

groupby를 사용하여 그룹 내에서 최대 값을 가진 행을 가져오는 방법

 문제 내용 

How do I find all rows in a pandas DataFrame which have the max value for count column, after grouping by ['Sp','Mt'] columns?

['Sp','Mt'] 열을 기준으로 그룹화 후, count 열에서 최대값을 가지는 행을 찾고 싶습니다. Pandas DataFrame에서 이를 어떻게 할 수 있을까요?

 

Example 1: the following DataFrame:

예시 1: 다음 DataFrame이 있습니다.
   Sp   Mt Value   count
0  MM1  S1   a     **3**
1  MM1  S1   n       2
2  MM1  S3   cb    **5**
3  MM2  S3   mk    **8**
4  MM2  S4   bg    **10**
5  MM2  S4   dgd     1
6  MM4  S2   rd      2
7  MM4  S2   cb      2
8  MM4  S2   uyi   **7**

 

Expected output is to get the result rows whose count is max in each group, like this:

그룹별로 count 열에서 최대값을 가지는 결과 행을 얻고 싶습니다. 예상 결과는 다음과 같습니다.
   Sp   Mt   Value  count
0  MM1  S1   a      **3**
2  MM1  S3   cb     **5**
3  MM2  S3   mk     **8**
4  MM2  S4   bg     **10** 
8  MM4  S2   uyi    **7**

 

Example 2:

예 2:
   Sp   Mt   Value  count
4  MM2  S4   bg     10
5  MM2  S4   dgd    1
6  MM4  S2   rd     2
7  MM4  S2   cb     8
8  MM4  S2   uyi    8

 

Expected output:

예상 출력:
   Sp   Mt   Value  count
4  MM2  S4   bg     10
7  MM4  S2   cb     8
8  MM4  S2   uyi    8

 

 

 높은 점수를 받은 Solution 

Firstly, we can get the max count for each group like this:

먼저, 다음과 같이 각 그룹의 최대값을 얻을 수 있습니다.
In [1]: df
Out[1]:
    Sp  Mt Value  count
0  MM1  S1     a      3
1  MM1  S1     n      2
2  MM1  S3    cb      5
3  MM2  S3    mk      8
4  MM2  S4    bg     10
5  MM2  S4   dgd      1
6  MM4  S2    rd      2
7  MM4  S2    cb      2
8  MM4  S2   uyi      7

In [2]: df.groupby(['Sp', 'Mt'])['count'].max()
Out[2]:
Sp   Mt
MM1  S1     3
     S3     5
MM2  S3     8
     S4    10
MM4  S2     7
Name: count, dtype: int64

 

To get the indices of the original DF you can do:

원본 DF의 인덱스를 얻으려면 다음을 수행할 수 있습니다:
In [3]: idx = df.groupby(['Sp', 'Mt'])['count'].transform(max) == df['count']

In [4]: df[idx]
Out[4]:
    Sp  Mt Value  count
0  MM1  S1     a      3
2  MM1  S3    cb      5
3  MM2  S3    mk      8
4  MM2  S4    bg     10
8  MM4  S2   uyi      7

 

Note that if you have multiple max values per group, all will be returned.

그룹별로 여러 최대값이 있는 경우, 모든 값이 반환됩니다.

 


Update

업데이트

 

On a Hail Mary chance that this is what the OP is requesting:

OP가 요청하는 것이 이것인지 확률이 낮지만:
In [5]: df['count_max'] = df.groupby(['Sp', 'Mt'])['count'].transform(max)

In [6]: df
Out[6]:
    Sp  Mt Value  count  count_max
0  MM1  S1     a      3          3
1  MM1  S1     n      2          3
2  MM1  S3    cb      5          5
3  MM2  S3    mk      8          8
4  MM2  S4    bg     10         10
5  MM2  S4   dgd      1         10
6  MM4  S2    rd      2          7
7  MM4  S2    cb      2          7
8  MM4  S2   uyi      7          7

 

 

 가장 최근 달린 Solution 

Many of these are great answers, but to help show scalability, on 2.8 million rows with varying amount of duplicates shows some startling differences. The fastest for my data was the sort by then drop duplicate (drop all but last marginally faster than sort descending and drop all but first)

이미 제시된 답변들 중 많은 것들이 좋은 답변이지만, 확장성을 보여주기 위해 중복된 행 수가 다른 280만 개의 행에서 시도해본 결과, sort 후 drop duplicate가 가장 빨랐습니다 (sort descending 후 drop all but first는 그다음으로 빨랐습니다).

 

  1. Sort Ascending, Drop duplicate keep last (2.22 s)
  2. Sort Descending, Drop Duplicate keep First (2.32 s)
  3. Transform Max within the loc function (3.73 s)
  4. Transform Max storing IDX then using loc select as second step (3.84 s)
  5. Groupby using Tail (8.98 s)
  6. IDMax with groupby and then using loc select as second step (95.39 s)
  7. IDMax with groupby within the loc select (95.74 s)
  8. NLargest(1) then using iloc select as a second step (> 35000 s ) - did not finish after running overnight
  9. NLargest(1) within iloc select (> 35000 s ) - did not finish after running overnight
1. 오름차순 정렬 후 drop duplicate keep last (2.22 s)
2. 내림차순 정렬 후 drop duplicate keep first (2.32 s)
3. loc 함수 내에서 Max 변환 (3.73 s)
4. IDX 저장 후 loc select 사용 (3.84 s)
5. Tail을 사용한 groupby (8.98 s)
6. groupby 후 loc select (95.39 s)
7. loc select 내에서 groupby를 사용한 IDMax (95.74 s)
8. iloc select 내에서 NLargest(1) 사용 (35000 s 초과) - 오랜 시간 후 종료되지 않음
9. iloc select 내에서 NLargest(1) 사용한 후 groupby (35000 s 초과) - 오랜 시간 후 종료되지 않음

 

As you can see Sort is 1/3 faster than transform and 75% faster than groupby. Everything else is up to 40x slower. In small datasets, this may not matter by much, but as you can see, this can significantly impact large datasets.

보시다시피 정렬은 변환보다 1/3, 그룹별 정렬보다 75% 더 빠릅니다. 다른 모든 것은 최대 40배 더 느립니다. 소규모 데이터 세트에서는 이 문제가 크게 중요하지 않을 수 있지만, 보시다시피 대규모 데이터 세트에 큰 영향을 미칠 수 있습니다.

 

 

 

출처 : https://stackoverflow.com/questions/15705630/get-the-rows-which-have-the-max-value-in-groups-using-groupby

반응형
댓글
공지사항
최근에 올라온 글