使用index_natsorted与mergesort对Pandas DataFrame按两列排序失败求助
DataFrame双列排序解决方案(自然排序+自定义分类顺序)
问题核心
需要同时实现:
- 按col[0]自然排序(规避字典序排序错误)
- 按col[2]的自定义顺序
['gene','mRNA','five_prime_UTR','CDS','three_prime_UTR']排序
但先执行reindex再调用sort_values会丢失col[0]的自然排序,原因是sort_values会全局重排,完全覆盖之前的索引顺序。
可行方案
方案1:添加自然排序辅助列,联合排序
通过辅助列记录col[0]的自然排序位置,再和col[2]共同作为排序依据:
from natsort import index_natsorted from pandas.api.types import CategoricalDtype # 1. 将col[2]设置为自定义有序分类 cat_dtype = CategoricalDtype( categories=['gene', 'mRNA', 'five_prime_UTR', 'CDS', 'three_prime_UTR'], ordered=True ) df[2] = df[2].astype(cat_dtype) # 2. 生成col[0]的自然排序辅助列 df['col0_rank'] = index_natsorted(df[0]) # 3. 按辅助列+col[2]排序,最后删除辅助列 df_sorted = df.sort_values(by=['col0_rank', 2], ascending=[True, True]) df_sorted = df_sorted.drop('col0_rank', axis=1)
方案2:利用sort_values的key参数(Pandas 1.1.0+)
直接通过key参数为col[0]指定自然排序逻辑,无需额外辅助列:
from natsort import natsort_keygen from pandas.api.types import CategoricalDtype # 1. 将col[2]设置为自定义有序分类 cat_dtype = CategoricalDtype( categories=['gene', 'mRNA', 'five_prime_UTR', 'CDS', 'three_prime_UTR'], ordered=True ) df[2] = df[2].astype(cat_dtype) # 2. 双列排序:col[0]用自然排序,col[2]用自定义分类顺序 df_sorted = df.sort_values( by=[0, 2], key=lambda col: natsort_keygen()(col) if col.name == 0 else col, ascending=[True, True] )
方案3:稳定排序的嵌套应用
借助mergesort的稳定性(相同值保留原有顺序),先按次要关键字排序,再按主要关键字排序:
from natsort import index_natsorted from pandas.api.types import CategoricalDtype # 1. 将col[2]设置为自定义有序分类 cat_dtype = CategoricalDtype( categories=['gene', 'mRNA', 'five_prime_UTR', 'CDS', 'three_prime_UTR'], ordered=True ) df[2] = df[2].astype(cat_dtype) # 2. 先按col[2]稳定排序,再按col[0]自然排序重索引 df_sorted = df.sort_values(by=2, kind='mergesort') df_sorted = df_sorted.reindex(index_natsorted(df_sorted[0]))
逻辑说明:先让col[2]按自定义顺序排好,再通过自然排序重索引col[0],此时同一col[0]分组内的行会保留之前col[2]的排序结果。
内容的提问来源于stack exchange,提问作者Fcallejas
相关产品推荐
相关产品推荐

