Python( pandas): usuwanie duplikatów na podstawie dwóch kolumn utrzymujących wiersz z wartością maksymalną w innej kolumnie

Mam ramkę danych, 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: Elsalex, 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.

Edytuj: Od pandas 0.18 w górę drugie rozwiązanie 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
 37
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
2018-01-08 17:22:37

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()
 7
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ć po prostu za pomocą funkcji pandas drop duplicates

df.drop_duplicates(['A','B'],keep= 'last')
 3
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

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()
 0
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