Python pandas: Usuń duplikaty kolumn a, zachowując wiersz o najwyższej wartości w kolumnie B

Mam ramkę danych z powtarzanymi wartościami w kolumnie A. chcę upuścić duplikaty, zachowując wiersz z najwyższą wartością w kolumnie B.

Więc to:

A B
1 10
1 20
2 30
2 40
3 10

Powinno się zmienić w to:

A B
1 20
2 40
3 10

Wes dodał kilka fajnych funkcji do upuszczania duplikatów: http://wesmckinney.com/blog/?p=340 . ale AFAICT, jest przeznaczony do dokładnych duplikatów, więc nie ma wzmianki o kryteriach wyboru, które wiersze zostaną zachowane.

Zgaduję, że prawdopodobnie jest łatwy sposób na zrób to - - - może tak proste, jak sortowanie ramki danych przed zrzuceniem duplikatów - - - ale nie znam wewnętrznej logiki groupby ' ego wystarczająco dobrze, aby to rozgryźć. Jakieś sugestie?

Author: Abe, 2012-09-19

8 answers

To zajmie Ostatnie. Ale nie maksimum:

In [10]: df.drop_duplicates(subset='A', keep="last")
Out[10]: 
   A   B
1  1  20
3  2  40
4  3  10

Możesz też zrobić coś takiego:

In [12]: df.groupby('A', group_keys=False).apply(lambda x: x.loc[x.B.idxmax()])
Out[12]: 
   A   B
A       
1  1  20
2  2  40
3  3  10
 100
Author: Wes McKinney,
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-10-04 18:03:43

Najlepsza odpowiedź wykonuje zbyt dużo pracy i wygląda na bardzo powolną dla większych zestawów danych. apply jest powolny i należy go unikać, jeśli to możliwe. ix jest przestarzały i należy go również unikać.

df.sort_values('B', ascending=False).drop_duplicates('A').sort_index()

   A   B
1  1  20
3  2  40
4  3  10

Lub po prostu pogrupuj według wszystkich innych kolumn i weź maksimum potrzebnej kolumny. df.groupby('A', as_index=False).max()

 16
Author: Ted Petrou,
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-08-09 16:24:35

Spróbuj tego:

df.groupby(['A']).max()
 7
Author: eumiro,
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
2012-09-19 15:10:56

Możesz również spróbować

df.drop_duplicates(subset='A', keep='last')

Odniosłem się do tego z https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.drop_duplicates.html

 2
Author: Venkat,
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-08-05 18:48:25

Myślę, że w Twoim przypadku nie potrzebujesz groupby. Posortowałbym po malejącej kolejności twoją kolumnę B, a następnie wrzuciłbym duplikaty do kolumny A i jeśli chcesz możesz też mieć nową ładną i czysty indeks tak:

df.sort_values('B', ascending=False).drop_duplicates('A').sort_index().reset_index(drop=True)
 1
Author: whateveros,
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-09-01 11:15:59

To również działa:

a=pd.DataFrame({'A':a.groupby('A')['B'].max().index,'B':a.groupby('A')       ['B'].max().values})
 0
Author: Mahesh,
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-01-14 15:16:38

Gdy już podane posty odpowiadają na pytanie, dokonałem małej zmiany dodając nazwę kolumny, na której zastosowana jest funkcja max() dla lepszej czytelności kodu.

df.groupby('A', as_index=False)['B'].max()
 0
Author: Bhagabat Behera,
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-06-24 12:43:15

Nie dam ci całej odpowiedzi( nie sądzę, że szukasz parsowania i zapisu do pliku), ale kluczowa wskazówka powinna wystarczyć: użyj funkcji set() Pythona, a następnie sorted() lub .sort() w połączeniu z .reverse():

>>> a=sorted(set([10,60,30,10,50,20,60,50,60,10,30]))
>>> a
[10, 20, 30, 50, 60]
>>> a.reverse()
>>> a
[60, 50, 30, 20, 10]
 -4
Author: Abhranil Das,
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
2012-09-19 15:10:29