现在pandas 在sort_values 和sort_index 中都支持key,您现在应该参考this other answer 并将所有赞成票发送到那里,因为它现在是正确的答案。
我会将我的答案留在这里,以供那些停留在旧 pandas 版本的人,或者作为历史的好奇心。
accepted answer 回答了所提出的问题。我还想添加如何在 DataFrame 中的列上使用 natsort,因为这将是下一个问题。
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
正如accepted answer 所示,按索引排序非常简单:
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
如果您想以相同的方式对列进行排序,则需要按照所需列的重新排序顺序对索引进行排序。 natsort 提供了方便的函数 index_natsorted 和 order_by_index 来做到这一点。
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
如果要按任意数量的列(或列和索引)重新排序,可以使用zip(或 Python2 上的 itertools.izip)指定对多列进行排序。给定的第一列将是主要排序列,然后是次要列,然后是第三列,等等......
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
pandas 开发人员告诉我,这是一种使用 Categorical 对象的替代方法,这是执行此操作的“正确”方法。这需要(据我所知)pandas >= 0.16.0。目前,它仅适用于列,但显然在 pandas >= 0.17.0 中它们将添加 CategoricalIndex,这将允许在索引上使用此方法。
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
Categorical 对象允许您定义DataFrame 使用的排序顺序。调用 reorder_categories 时给出的元素必须是唯一的,因此对列“b”的调用 set。
我让用户来决定这是否比reindex 方法更好,因为它要求您在DataFrame 中排序之前独立地对列数据进行排序(尽管我认为第二次排序是高效)。
完全披露,我是natsort作者。