Il accepted answer risponde alla domanda che viene posta. Mi piacerebbe anche aggiungere come usare natsort
su colonne in un DataFrame
, dal momento che sarà la prossima domanda posta.
In [1]: from pandas import DataFrame
In [2]: from natsort import natsorted, index_natsorted, order_by_index
In [3]: df = DataFrame({'a': ['a5', 'a1', 'a10', 'a2', 'a12'], 'b': ['b1', 'b1', 'b2', 'b2', 'b1']}, index=['0hr', '128hr', '72hr', '48hr', '96hr'])
In [4]: df
Out[4]:
a b
0hr a5 b1
128hr a1 b1
72hr a10 b2
48hr a2 b2
96hr a12 b1
quanto accepted answer spettacoli, l'ordinamento per l'indice è abbastanza semplice:
In [5]: df.reindex(index=natsorted(df.index))
Out[5]:
a b
0hr a5 b1
48hr a2 b2
72hr a10 b2
96hr a12 b1
128hr a1 b1
Se si desidera ordinare su una colonna nello stesso modo, è necessario ordinare l'indice dall'ordine che la colonna desiderata è stata riordinata. natsort
fornisce le funzioni comfort index_natsorted
e order_by_index
per fare proprio questo.
In [6]: df.reindex(index=order_by_index(df.index, index_natsorted(df.a)))
Out[6]:
a b
128hr a1 b1
48hr a2 b2
0hr a5 b1
72hr a10 b2
96hr a12 b1
In [7]: df.reindex(index=order_by_index(df.index, index_natsorted(df.b)))
Out[7]:
a b
0hr a5 b1
128hr a1 b1
96hr a12 b1
72hr a10 b2
48hr a2 b2
Se si desidera riordinare da un numero arbitrario di colonne (o una colonna e l'indice), è possibile utilizzare zip
(o itertools.izip
su python2) per specificare l'ordinamento su più colonne. La prima colonna data sarà la colonna di ordinamento primario, secondario, terziario poi, ecc ...
In [8]: df.reindex(index=order_by_index(df.index, index_natsorted(zip(df.b, df.a))))
Out[8]:
a b
128hr a1 b1
0hr a5 b1
96hr a12 b1
48hr a2 b2
72hr a10 b2
In [9]: df.reindex(index=order_by_index(df.index, index_natsorted(zip(df.b, df.index))))
Out[9]:
a b
0hr a5 b1
96hr a12 b1
128hr a1 b1
48hr a2 b2
72hr a10 b2
Ecco un metodo alternativo utilizzando Categorical
oggetti che è stato detto dai pandas
sviluppatori è il modo "corretto" per farlo. Ciò richiede (per quanto posso vedere) panda> = 0.16.0. Attualmente funziona solo su colonne, ma apparentemente in panda> = 0.17.0 aggiungeranno CategoricalIndex
che consentirà di utilizzare questo metodo su un indice.
In [1]: from pandas import DataFrame
In [2]: from natsort import natsorted
In [3]: df = DataFrame({'a': ['a5', 'a1', 'a10', 'a2', 'a12'], 'b': ['b1', 'b1', 'b2', 'b2', 'b1']}, index=['0hr', '128hr', '72hr', '48hr', '96hr'])
In [4]: df.a = df.a.astype('category')
In [5]: df.a.cat.reorder_categories(natsorted(df.a), inplace=True, ordered=True)
In [6]: df.b = df.b.astype('category')
In [8]: df.b.cat.reorder_categories(natsorted(set(df.b)), inplace=True, ordered=True)
In [9]: df.sort('a')
Out[9]:
a b
128hr a1 b1
48hr a2 b2
0hr a5 b1
72hr a10 b2
96hr a12 b1
In [10]: df.sort('b')
Out[10]:
a b
0hr a5 b1
128hr a1 b1
96hr a12 b1
72hr a10 b2
48hr a2 b2
In [11]: df.sort(['b', 'a'])
Out[11]:
a b
128hr a1 b1
0hr a5 b1
96hr a12 b1
48hr a2 b2
72hr a10 b2
L'oggetto Categorical
consente di definire un ordinamento per la DataFrame
da usare.Gli elementi forniti quando si chiama reorder_categories
devono essere univoci, da qui la chiamata a set
per la colonna "b".
Lascio l'utente a decidere se questo è meglio che il metodo reindex
o no, dal momento che richiede di ordinare i dati della colonna in modo indipendente prima della cernita all'interno del DataFrame
(anche se immagino che secondo tipo è piuttosto efficiente).
Full disclosure, sono l'autore natsort
.
@sethMMorton Supponevo che mi sarebbe piaciuto 'df3.index' per essere uguale a' c' mentre ordinai i dati per mantenerlo in linea con i suoi valori di indice – agf1997
Sarebbe bello se 'pd.sort' avesse un tasto' 'opzione, ma non è così. [Questa risposta] (http://stackoverflow.com/a/27009771/1399279) fornisce una soluzione alternativa che consente di passare una chiave generata da 'natsort_keygen'. – SethMMorton
Ho appena fatto una richiesta ufficiale agli sviluppatori 'pandas' di aggiungere' chiave' ai metodi 'sort' qui: https://github.com/pydata/pandas/issues/9855 – SethMMorton