按正确顺序排列染色体列表



一个看似简单的问题,但事实证明它有点令人烦恼。我有一个染色体列表(有23条染色体-染色体1到21,然后是染色体X和染色体Y),像这样:

['chr11','chr14','chr16','chr13','chr4','chr13','chr2','chr1','chr2','chr3','chr14','chrX',]

我想按以下顺序排序:

['chr1', 'chr2','chr2','chr3','chr4','chr11','chr13','chr13', 'chr14','chr14','chr16','chrX']

然而,由于python的sort的字典性质,它将对chr1, chr10, chr11, chr12...chr2,等排序,因为我有染色体X,按它们的整数值排序似乎也不是一个选择。我是否可能需要指定一个唯一的键来对列表进行排序?或者有什么明显的解决方案我错过了。

您可以使用natsorted,毕竟您想要的是自然排序;)

l = ['chr11','chr14','chr16','chr13','chr4','chr13','chr2',
'chr1','chr2','chr3','chr14','chrX','chrY']
from natsort import natsorted
out = natsorted(l)

输出:

['chr1', 'chr2', 'chr2', 'chr3', 'chr4', 'chr11', 'chr13',
'chr13', 'chr14', 'chr14', 'chr16', 'chrX', 'chrY']

@mozway已经提到的natsort是最快的方法。

这里的解决方案不使用外部库。

sorted(l, key=lambda x: int(val) if (val:=x[3:]).isnumeric() else ord(val))

给出相同的输出。

您可以尝试在lambda函数中分别替换X和Y中的22和23,然后替换char值,然后仅使用字符串的int部分对列表进行排序

l = ['chr1', 'chr2','chr2','chr3','chr4','chr11','chr13','chr13', 'chr14','chr14','chr16','chrX']
sorted( l, key= lambda x: int(x.replace('X','22').replace('Y','23').replace('chr','')))
# OUTPUT
['chr1', 'chr2', 'chr2', 'chr3', 'chr4', 'chr11', 'chr13', 'chr13', 'chr14', 'chr14', 'chr16','chrX']

您可以创建一个自定义密钥:

key={s:i for i,s in 
enumerate([f'chr{x}' for x in list(range(1,22))+['X','Y']],1)}
>>> key
{'chr1': 1, 'chr2': 2, 'chr3': 3, 'chr4': 4, 'chr5': 5, 'chr6': 6, 'chr7': 7, 'chr8': 8, 'chr9': 9, 'chr10': 10, 'chr11': 11, 'chr12': 12, 'chr13': 13, 'chr14': 14, 'chr15': 15, 'chr16': 16, 'chr17': 17, 'chr18': 18, 'chr19': 19, 'chr20': 20, 'chr21': 21, 'chrX': 22, 'chrY': 23}

然后在sorted中使用该键作为查找:

li = ['chr11','chr14','chr16','chr13','chr4','chr13','chr2',
'chr1','chr2','chr3','chr14','chrX','chrY']
>>> sorted(li, key=lambda s: key[s])
['chr1', 'chr2', 'chr2', 'chr3', 'chr4', 'chr11', 'chr13', 'chr13', 'chr14', 'chr14', 'chr16', 'chrX', 'chrY']

或者,您可以使用正则表达式进行自然排序以解析出数字:

import re
sli=sorted(li, key=lambda e: 
[int(s) if s.isdigit() else s for s in re.findall(r'd+|D+', e)])
>>> sli
['chr1', 'chr2', 'chr2', 'chr3', 'chr4', 'chr11', 'chr13', 'chr13', 'chr14', 'chr14', 'chr16', 'chrX', 'chrY']

自定义键将明显更快——如果你有数十亿的排序使用它。

最新更新