现在,pandas
在sort_values
和sort_index
中均支持key
,因此您现在应该参考这个答案并将所有的投票都发送到那里,因为它现在是正确的答案。
我将保留我的答案,以供那些卡在旧版pandas
上的人使用,或者作为历史的好奇心。
被接受的答案回答了所提出的问题。 我想补充一下如何在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
正如被接受的回答所示,按索引排序是相当简单的:
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
这里是另一种使用
Categorical
对象的方法,这是由
pandas
开发人员告诉我的“适当”方法。需要 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
的作者。
df3.index
应该与c
相同,以使其与索引值保持一致。 - agf1997pd.sort
有一个key
选项会很好,但它没有。这个答案提供了一个解决方法,可以让您传递从natsort_keygen
生成的键。 - SethMMortonpandas
开发人员提交了一个正式请求,要求在此处的sort
方法中添加key
:https://github.com/pydata/pandas/issues/9855 - SethMMortonpandas
已经有了sort_values
的key
参数,https://dev59.com/YV0b5IYBdhLWcg3wIOF9#63890954 现在应该成为被接受的答案。 - SethMMorton