Usuń duplikaty z ramki danych, na podstawie dwóch kolumn A, B, zachowując wiersz z wartością maksymalną w innej kolumnie C

Mam ramkę danych pandy, która zawiera duplikaty wartości według dwóch kolumn (A i B):

A B C
1 2 1
1 2 4
2 7 1
3 4 0
3 4 8

Chcę usunąć duplikaty zachowując wiersz o maksymalnej wartości w kolumnie C. prowadziłoby to do:

A B C
1 2 4
2 7 1
3 4 8
Nie wiem, jak to zrobić. Czy powinienem użyć drop_duplicates(), czegoś innego?
Author: smci, 2015-08-19

4 answers

Możesz to zrobić używając group by:

c_maxes = df.groupby(['A', 'B']).C.transform(max)
df = df.loc[df.C == c_maxes]

c_maxes jest Series z maksymalnych wartości C w każdej grupie, ale która jest tej samej długości i z tym samym indeksem co df. Jeśli nie użyłeś .transform, drukowanie c_maxes może być dobrym pomysłem, aby zobaczyć, jak to działa.

Innym podejściem używającym drop_duplicates byłoby

df.sort('C').drop_duplicates(subset=['A', 'B'], take_last=True)

Nie wiem, który jest bardziej wydajny, ale myślę, że pierwsze podejście, ponieważ nie wymaga sortowania.

EDIT: From pandas 0.18 up the drugim rozwiązaniem byłoby

df.sort_values('C').drop_duplicates(subset=['A', 'B'], keep='last')

Lub, alternatywnie,

df.sort_values('C', ascending=False).drop_duplicates(subset=['A', 'B'])

W każdym razie rozwiązanie groupby wydaje się być znacznie bardziej wydajne:

%timeit -n 10 df.loc[df.groupby(['A', 'B']).C.max == df.C]
10 loops, best of 3: 25.7 ms per loop

%timeit -n 10 df.sort_values('C').drop_duplicates(subset=['A', 'B'], keep='last')
10 loops, best of 3: 101 ms per loop
 86
Author: JoeCondron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-30 16:33:40

Możesz to zrobić po prostu za pomocą funkcji pandas drop duplicates

df.drop_duplicates(['A','B'],keep= 'last')
 32
Author: Sudharsan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-07 08:24:34

Myślę, że groupby powinno działać.

df.groupby(['A', 'B']).max()['C']

Jeśli potrzebujesz ramki danych z powrotem, możesz połączyć wywołanie Reset indeksu.

df.groupby(['A', 'B']).max()['C'].reset_index()
 10
Author: b10n,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-19 11:39:42

Możesz to zrobić z drop_duplicates jak chciałeś

# initialisation
d = pd.DataFrame({'A' : [1,1,2,3,3], 'B' : [2,2,7,4,4],  'C' : [1,4,1,0,8]})

d = d.sort_values("C", ascending=False)
d = d.drop_duplicates(["A","B"])

Jeśli ważne jest, aby uzyskać tę samą kolejność

d = d.sort_index()
 5
Author: AlexT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-05 13:47:41