Mam ramkę danych Pythona pandy, w której kolumna zawiera nazwę miesiąca.Niestandardowe sortowanie w pandach Dataframe
Jak mogę zrobić zwyczaj sortowania przy użyciu słownika, na przykład:
custom_dict = {'March':0, 'April':1, 'Dec':3}
Mam ramkę danych Pythona pandy, w której kolumna zawiera nazwę miesiąca.Niestandardowe sortowanie w pandach Dataframe
Jak mogę zrobić zwyczaj sortowania przy użyciu słownika, na przykład:
custom_dict = {'March':0, 'April':1, 'Dec':3}
Pandy 0.15 wprowadzono Categorical Series, który pozwala o wiele bardziej przejrzysty sposób:
Najpierw ustaw kolumnę miesiąca jako kategorię i określ kolejność, której chcesz użyć.
In [21]: df['m'] = pd.Categorical(df['m'], ["March", "April", "Dec"])
In [22]: df # looks the same!
Out[22]:
a b m
0 1 2 March
1 5 6 Dec
2 3 4 April
Teraz, kiedy posortować kolumnę miesiąc będzie rozwiązać w odniesieniu do tej listy:
In [23]: df.sort("m")
Out[23]:
a b m
0 1 2 March
2 3 4 April
1 5 6 Dec
Uwaga: Jeśli wartość nie znajduje się na liście zostanie skonwertowana do Nan.
Starszy odpowiedź dla zainteresowanych ...
Można by stworzyć serię pośrednika i set_index
na tym:
df = pd.DataFrame([[1, 2, 'March'],[5, 6, 'Dec'],[3, 4, 'April']], columns=['a','b','m'])
s = df['m'].apply(lambda x: {'March':0, 'April':1, 'Dec':3}[x])
s.sort()
In [4]: df.set_index(s.index).sort()
Out[4]:
a b m
0 1 2 March
1 3 4 April
2 5 6 Dec
Jak zauważył, w nowszych pand, Seria ma metodę replace
, aby zrobić to bardziej elegancko:
s = df['m'].replace({'March':0, 'April':1, 'Dec':3})
Niewielka różnica polega na tym, że nie podniesie się, jeśli istnieje wartość spoza słownika (pozostanie taka sama).
's = df ['m']. Replace ({'March': 0, 'April': 1, 'Dec': 3})' działa również dla linii 2 - tylko dla dobra nauki pandy jak ja – kdauria
@kdauria dobre miejsce! (od dłuższego czasu napisałem to!) zamień zdecydowanie najlepszą opcję, innym jest użycie '.apply ({'March': 0, 'April': 1, 'Dec': 3} .get)' :) In 0.15 będziemy mieć kategorię/kolumny kategorialne, więc najlepszym sposobem będzie użycie tego, a następnie sortowanie będzie działać. –
@AndyHayden Miałem możliwość zastąpienia drugiej linii metodą "zastąp". Mam nadzieję, że to jest OK. –
import pandas as pd
custom_dict = {'March':0,'April':1,'Dec':3}
df = pd.DataFrame(...) # with columns April, March, Dec (probably alphabetically)
df = pd.DataFrame(df, columns=sorted(custom_dict, key=custom_dict.get))
zwraca DataFrame z kolumnami marcu, kwietniu, gru
To działa i łatwiej pisać w dowolnym istniejącym kodzie. Dziękuję Ci! – posdef
Trochę za późno, ale oto sposób na utworzenie funkcji, która sortuje obiekty Series, DataFrame i multiindex DataFrame przy użyciu dowolnych funkcji.
Korzystam z metody df.iloc[index]
, która odwołuje się do wiersza w serii/DataFrame według pozycji (w porównaniu do df.loc
, która odnosi się według wartości). Korzystanie z tego, po prostu mieć funkcję zwracającą szereg argumentów pozycyjnych:
def sort_pd(key=None,reverse=False,cmp=None):
def sorter(series):
series_list = list(series)
return [series_list.index(i)
for i in sorted(series_list,key=key,reverse=reverse,cmp=cmp)]
return sorter
można użyć tego do tworzenia własnych funkcji sortowania. Działa to na dataframe stosowanego w odpowiedzi Andy Haydena:
df = pd.DataFrame([
[1, 2, 'March'],
[5, 6, 'Dec'],
[3, 4, 'April']],
columns=['a','b','m'])
custom_dict = {'March':0, 'April':1, 'Dec':3}
sort_by_custom_dict = sort_pd(key=custom_dict.get)
In [6]: df.iloc[sort_by_custom_dict(df['m'])]
Out[6]:
a b m
0 1 2 March
2 3 4 April
1 5 6 Dec
ten działa również na multiindex DataFrames i obiektów Seria:
months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
df = pd.DataFrame([
['New York','Mar',12714],
['New York','Apr',89238],
['Atlanta','Jan',8161],
['Atlanta','Sep',5885],
],columns=['location','month','sales']).set_index(['location','month'])
sort_by_month = sort_pd(key=months.index)
In [10]: df.iloc[sort_by_month(df.index.get_level_values('month'))]
Out[10]:
sales
location month
Atlanta Jan 8161
New York Mar 12714
Apr 89238
Atlanta Sep 5885
sort_by_last_digit = sort_pd(key=lambda x: x%10)
In [12]: pd.Series(list(df['sales'])).iloc[sort_by_last_digit(df['sales'])]
Out[12]:
2 8161
0 12714
3 5885
1 89238
Dla mnie to czuje się czysty, ale używa operacji Pythona mocno zamiast polegania na zoptymalizowanych operacjach pand. Nie przeprowadzałem żadnych testów warunków skrajnych, ale wyobrażam sobie, że może to działać powoli w przypadku bardzo dużych obiektów DataFrames. Nie wiesz, jak wydajność jest porównywana z dodawaniem, sortowaniem i usuwaniem kolumny. Wszelkie wskazówki dotyczące przyspieszenia kodu będą mile widziane!
Czy ta praca służy do sortowania wielu kolumn/indeksów? – ConanG
tak, ale wybrana odpowiedź jest o wiele lepszym sposobem na zrobienie tego. Jeśli masz wiele indeksów, po prostu ułóż je zgodnie z preferowanym porządkiem sortowania, a następnie użyj polecenia 'df.sort_index()', aby posortować wszystkie poziomy indeksu. – delgadom
Czy kolumna zawiera nazwę miesiąca oznacza, że istnieje kolumna zawierająca nazwy miesięcy (jako moją odpowiedź) lub wiele kolumn z nazwami kolumn jako nazwami miesięcy (jak eumiro)? –