如何基于指定规则对Pandas DataFrame分组排序并保留组内顺序
问题描述
我有如下Pandas DataFrame:
sample closest_signature distance patient cluster correlation biopsy similarity n_biopsy 0 21506-A HU.1 0.416795 21506 HU.1 0.994611 A 2.399261 2.0 1 21506-B HU.1 0.340269 21506 HU.1 0.993852 B 2.938855 2.0 2 21507-A HU.3 0.181289 21507 HU.3 0.868993 A 5.516052 3.0 3 21507-B HU.3 0.128398 21507 HU.3 0.972968 B 7.788282 3.0 4 21507-C HU.3 0.117186 21507 HU.3 0.949540 C 8.533432 3.0 5 21521-A HU.2 0.111720 21521 HU.2 0.956889 A 8.950942 2.0 6 21521-B HU.2 0.116082 21521 HU.2 0.974804 B 8.614610 2.0 7 21531-A HU.4 0.251558 21531 ND 0.560867 A 3.975227 2.0 8 21531-B HU.2 0.197108 21531 HU.2 0.890214 B 5.073356 2.0 9 21543-A HU.2 0.184331 21543 HU.2 0.973885 A 5.425033 6.0 10 21543-B HU.2 0.151444 21543 HU.2 0.990204 B 6.603119 6.0 11 21543-C HU.2 0.156038 21543 HU.2 0.989900 C 6.408698 6.0 12 21543-D HU.2 0.196920 21543 HU.2 0.939929 D 5.078191 6.0 13 21543-E HU.1 0.234311 21543 HU.1 0.980673 E 4.267841 6.0 14 21543-F HU.2 0.152050 21543 HU.2 0.989276 F 6.576796 6.0
需要实现的排序规则:
- 每个患者组的排序依据是该组中后缀为A的样本的
closest_signature值,组内所有样本统一用这个值排序 - 患者组按
n_biopsy降序排列,同时保留组内样本从A到Z的原有顺序
预期结果:
sample closest_signature distance patient cluster correlation biopsy similarity n_biopsy 0 21506-A HU.1 0.416795 21506 HU.1 0.994611 A 2.399261 2.0 1 21506-B HU.1 0.340269 21506 HU.1 0.993852 B 2.938855 2.0 9 21543-A HU.2 0.184331 21543 HU.2 0.973885 A 5.425033 6.0 10 21543-B HU.2 0.151444 21543 HU.2 0.990204 B 6.603119 6.0 11 21543-C HU.2 0.156038 21543 HU.2 0.989900 C 6.408698 6.0 12 21543-D HU.2 0.196920 21543 HU.2 0.939929 D 5.078191 6.0 13 21543-E HU.1 0.234311 21543 HU.1 0.980673 E 4.267841 6.0 14 21543-F HU.2 0.152050 21543 HU.2 0.989276 F 6.576796 6.0 5 21521-A HU.2 0.111720 21521 HU.2 0.956889 A 8.950942 2.0 6 21521-B HU.2 0.116082 21521 HU.2 0.974804 B 8.614610 2.0 2 21507-A HU.3 0.181289 21507 HU.3 0.868993 A 5.516052 3.0 3 21507-B HU.3 0.128398 21507 HU.3 0.972968 B 7.788282 3.0 4 21507-C HU.3 0.117186 21507 HU.3 0.949540 C 8.533432 3.0 7 21531-A HU.4 0.251558 21531 ND 0.560867 A 3.975227 2.0 8 21531-B HU.2 0.197108 21531 HU.2 0.890214 B 5.073356 2.0
之前尝试过直接按n_biopsy和patient排序,以及创建复合键,但都无法满足需求,要么排序依据错误,要么丢失组内顺序。
解决方案
完全可以实现你的需求,步骤如下:
- 提取每个患者组的A样本签名:筛选出所有后缀为A的样本,提取对应的
patient和closest_signature,将这个映射关联到原DataFrame中,作为分组排序的依据列。 - 保留组内顺序:直接用
biopsy列作为组内排序的依据,保证样本按A到Z的顺序排列。 - 多键排序:按
n_biopsy降序、新生成的A样本签名升序、patient(确保组内聚合)、biopsy升序排序,最后重置索引即可。
具体代码实现:
# 1. 提取每个患者的A样本closest_signature a_signatures = df[df['sample'].str.endswith('-A')][['patient', 'closest_signature']].rename(columns={'closest_signature': 'a_closest_signature'}) # 2. 将该签名关联到原DataFrame df_with_key = df.merge(a_signatures, on='patient', how='left') # 3. 执行排序:n_biopsy降序,a_closest_signature升序,patient确保组内聚合,biopsy升序保留组内顺序 sorted_df = df_with_key.sort_values( by=['n_biopsy', 'a_closest_signature', 'patient', 'biopsy'], ascending=[False, True, True, True] ).drop(columns='a_closest_signature') # 可选:删除临时列 # 重置索引(可选) sorted_df = sorted_df.reset_index(drop=True) print(sorted_df)
代码说明:
- 第一步筛选出所有
sample以-A结尾的行,提取患者ID和对应的签名,确保每个患者只有一条记录,作为该组的统一排序依据。 - 第二步用
merge将这个签名映射到原DataFrame的每一行,让同一患者的所有样本都带有这个统一的排序键。 - 第三步排序时,先按
n_biopsy降序分组,同一n_biopsy内按A样本的签名升序排列患者组,再用patient保证同一患者的样本聚在一起,最后用biopsy升序保留A到Z的顺序。
执行这段代码后,就能得到你预期的排序结果,同时完全保留组内样本的原有顺序。
内容的提问来源于stack exchange,提问作者Einar
相关产品推荐
相关产品推荐

