2012-09-19 11 views
58

Mam ramkę danych z wartościami powtórzeń w kolumnie A. Chcę usunąć duplikaty, zachowując wiersz o najwyższej wartości w kolumnie B.python pandy: Usuń duplikaty według kolumn A, zachowując wiersz o najwyższej wartości w kolumnie B

Więc tak:

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

powinien przekształcić się w ten sposób:

A B 
1 20 
2 40 
3 10 

Wes dodał kilka ciekawych funkcjonalności do spadku duplikaty: http://wesmckinney.com/blog/?p=340. Ale AFAICT, jest przeznaczony do dokładnych duplikatów, więc nie ma żadnej wzmianki o kryteriach wyboru, które wiersze zostaną zachowane.

Zgaduję, że prawdopodobnie jest to prosty sposób - może tak łatwo jak sortowanie ramek danych przed upuszczeniem duplikatów --- ale nie znam wewnętrznej logiki groupby na tyle dobrze, aby to zrozumieć. Jakieś sugestie?

+1

Należy pamiętać, że adres URL w pytaniu pojawia EOL. – DaveL17

+0

Dla idiomatycznego i wydajnego sposobu, [zobacz to rozwiązanie poniżej] (https://stackoverflow.com/a/41650846/3707607). –

Odpowiedz

77

ten trwa ostatni. Nie maksymalna choć:

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

Można zrobić też 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 
+9

Mała uwaga: Parametry 'cols' i' take_last' są zamortyzowane i zostały zastąpione przez parametry 'subset' i' keep'. http://pandas.pydata.org/pandas-docs/version/0.17.1/generated/pandas.DataFrame.drop_duplicates.html – Jezzamon

+0

jak @Jezzamon mówi: 'FutureWarning: the take_last = Prawdziwe słowo kluczowe jest przestarzałe, użyj keep = ' last 'zamiast' –

+0

Czy istnieje powód, aby nie używać 'df.sort_values ​​(by = [' B ']). drop_duplicates (podzbiór = [' A '], keep =' last ')'? Chodzi mi o to, że wartości sort_s wydają mi się bezpieczne, ale nie mam pojęcia, czy tak naprawdę jest. – josh

-3

ja nie zamierzam dać ci całą odpowiedź (nie sądzę szukasz analizowania i zapisywania do pliku części tak), ale kluczową wskazówkę powinno wystarczyć: set() funkcji w Pythonie, a następnie sorted() lub .sort() 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] 
+6

Może się mylę, ale przekształcam pandas DataFrame jako zestaw, a następnie jego konwersja wydaje się bardzo nieskutecznym sposobem na rozwiązanie tego problemu.Robię analizę logów, więc zastosuję to do bardzo dużych zestawów danych. – Abe

+0

Niestety, nie wiem zbyt wiele na temat tego konkretnego scenariusza, więc może się zdarzyć, że moja ogólna odpowiedź nie okaże się zbyt skuteczna dla twojego problemu. –

7

Spróbuj tego:

df.groupby(['A']).max() 
+1

Czy znasz najlepszy język, aby ponownie zindeksować to, aby wyglądać jak oryginalna DataFrame? Próbowałem to rozgryźć, kiedy mnie ninja. : ^) – DSM

+3

Schludny. Co się stanie, jeśli ramka danych zawiera więcej kolumn (np. C, D, E)? Max nie działa w tym przypadku, ponieważ musimy określić, że B to jedyna kolumna, która musi zostać zmaksymalizowana. – Abe

+1

@DSM Sprawdź link w oryginalnym pytaniu. Jest jakiś kod do ponownego indeksowania pogrupowanej ramki danych. – Abe

12

Górny odpowiedź robi zbyt dużo pracy i wydaje się być bardzo powolne dla dużych zbiorów danych. apply jest powolny i powinno się go unikać, jeśli to możliwe. ix jest przestarzałe 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 pozostałych kolumn i weź maksimum kolumny, której potrzebujesz. df.groupby('A', as_index=False).max()

0

to działa również:

a=pd.DataFrame({'A':a.groupby('A')['B'].max().index,'B':a.groupby('A')  ['B'].max().values}) 
+0

Ten fragment kodu może rozwiązać pytanie, [w tym wyjaśnienie] (// meta.stackexchange.com/questions/114762/explaining-entirely-code-ans -answers) naprawdę pomaga poprawić jakość twojego postu. Pamiętaj, że odpowiadasz na pytanie przeznaczone dla czytelników w przyszłości, a te osoby mogą nie znać powodów sugestii dotyczących kodu. Proszę również starać się nie tłumić kodu za pomocą komentarzy wyjaśniających, co zmniejsza czytelność zarówno kodu, jak i objaśnień! – Carpetsmoker

0

Myślę, że w twoim przypadku tak naprawdę nie potrzebują Grupuj według. Chciałbym sortować według malejącej swoją kolumnę B, a następnie upuść duplikaty w kolumnie A i jeśli chcesz, możesz też mieć nowe ładne i czysty indeks tak:

df.sort_values('B', ascending=False).drop_duplicates('A').sort_index().reset_index(drop=True) 
+0

jak to się różni od innych postów? – DJK

Powiązane problemy