판다들은 각 그룹에서 최고 n개의 기록을 가지고 있다.
다음과 같은 팬더 DataFrame이 있다고 가정해 보겠습니다.
df = pd.DataFrame({'id':[1,1,1,2,2,2,2,3,4],'value':[1,2,3,1,2,3,4,1,1]})
다음과 같습니다.
id value
0 1 1
1 1 2
2 1 3
3 2 1
4 2 2
5 2 3
6 2 4
7 3 1
8 4 1
다음과 같이 각 ID에 대해 상위 2개의 레코드가 있는 새로운 Data Frame을 얻고 싶습니다.
id value
0 1 1
1 1 2
3 2 1
4 2 2
7 3 1
8 4 1
그룹 내 번호부여 레코드로 할 수 있습니다.groupby
:
dfN = df.groupby('id').apply(lambda x:x['value'].reset_index()).reset_index()
다음과 같습니다.
id level_1 index value
0 1 0 0 1
1 1 1 1 2
2 1 2 2 3
3 2 0 3 1
4 2 1 4 2
5 2 2 5 3
6 2 3 6 4
7 3 0 7 1
8 4 0 8 1
원하는 출력에 대해 다음을 수행합니다.
dfN[dfN['level_1'] <= 1][['id', 'value']]
출력:
id value
0 1 1
1 1 2
3 2 1
4 2 2
7 3 1
8 4 1
하지만 이를 위해 더 효과적이고 우아한 접근법이 있을까요?또, 각 그룹내의 레코드에 대해서, 보다 우아한 어프로치가 있습니다(예를 들면, SQL 창 함수 row_number()).
해보셨어요?
df.groupby('id').head(2)
출력 생성:
id value
id
1 0 1 1
1 1 2
2 3 2 1
4 2 2
3 7 3 1
4 8 4 1
(데이터에 따라서는 사전에 주문/구매가 필요할 수 있습니다.)
편집: 질문자가 언급한 바와 같이
df.groupby('id').head(2).reset_index(drop=True)
MultiIndex를 제거하고 결과를 평탄화하려면:
id value
0 1 1
1 1 2
2 2 1
3 2 2
4 3 1
5 4 1
0.14.1 이후로는nlargest
그리고.nsmallest
에서groupby
오브젝트:
In [23]: df.groupby('id')['value'].nlargest(2)
Out[23]:
id
1 2 3
1 2
2 6 4
5 3
3 7 1
4 8 1
dtype: int64
원래 인덱스가 들어간다는 것도 조금 이상하지만 원래 인덱스가 어떤 것이었느냐에 따라 매우 유용할 수 있습니다.
관심없으시면....reset_index(level=1, drop=True)
완전히 없애기 위해서요.
(주의: 0.17.1부터는 DataFrameGroupBy에서도 이 작업을 수행할 수 있게 됩니다만, 현재로서는Series
그리고.SeriesGroupBy
.)
전체 데이터를 미리 정렬하는 데 시간이 많이 걸릴 수 있습니다.먼저 그룹화하여 각 그룹에 대해 topk를 수행할 수 있습니다.
g = df.groupby(['id']).apply(lambda x: x.nlargest(topk,['value'])).reset_index(drop=True)
df.groupby('id').apply(lambda x : x.sort_values(by = 'value', ascending = False).head(2).reset_index(drop = True))
- 여기서 정렬 값 오름차순 false는 최대값과 비슷하고 True는 최소값과 비슷합니다.
- 헤드 내부의 값은 각 그룹에 대해 표시할 값의 수를 얻기 위해 n개의 가장 큰 내부의 값과 동일합니다.
- reset_index는 옵션이며 필요하지 않습니다.
중복된 값에 대해 작동합니다.
top-n 값에 중복된 값이 있고 원하는 값만 있으면 다음과 같이 할 수 있습니다.
import pandas as pd
ifile = "https://raw.githubusercontent.com/bhishanpdl/Shared/master/data/twitter_employee.tsv"
df = pd.read_csv(ifile,delimiter='\t')
print(df.query("department == 'Audit'")[['id','first_name','last_name','department','salary']])
id first_name last_name department salary
24 12 Shandler Bing Audit 110000
25 14 Jason Tom Audit 100000
26 16 Celine Anston Audit 100000
27 15 Michale Jackson Audit 70000
If we do not remove duplicates, for the audit department we get top 3 salaries as 110k,100k and 100k.
If we want to have not-duplicated salaries per each department, we can do this:
(df.groupby('department')['salary']
.apply(lambda ser: ser.drop_duplicates().nlargest(3))
.droplevel(level=1)
.sort_index()
.reset_index()
)
This gives
department salary
0 Audit 110000
1 Audit 100000
2 Audit 70000
3 Management 250000
4 Management 200000
5 Management 150000
6 Sales 220000
7 Sales 200000
8 Sales 150000
언급URL : https://stackoverflow.com/questions/20069009/pandas-get-topmost-n-records-within-each-group
'itsource' 카테고리의 다른 글
Maria용 Automysql 백업 구성DB (0) | 2022.10.26 |
---|---|
Vue: 계산된 속성이 하위 구성 요소로 전달되지 않음(콘솔은 "빈 문자열"을 기록함) (0) | 2022.10.26 |
Python에서 객체에 속성이 있는지 확인하려면 어떻게 해야 합니까? (0) | 2022.10.26 |
열에서 고유한 값 선택 (0) | 2022.10.26 |
콜과 신청의 차이점은 무엇입니까? (0) | 2022.10.26 |