我的基因组数据集包含基本消息,如下所示:
位置samp1 samp2 samp2 samp3 samp4 samp5 samp6 ...
posA T T T T T T ... ... posB G A A G G A A ...
posC G G G G G G ...
......
此文件有100000多行,每行包含200个200个样本的基数
现在我想删除每个样本中具有高相似基数的位置,下面的图片是100%相同,我将删除其中一个
我们将类似的比率定义为(相似的基数)/(序列长度):
posH C C C C C C C
posI A C C C A C C C
posH和posI的相似度为6/8 = 75% 根据需要,类似比率高于99%被视为高度相似,并删除其中一个类似的位置。
我如何有效地在python中完成这项工作? 谢谢。
答案 0 :(得分:5)
6/8
与posH
之间posI
的相似性,看起来您想要归一化hamming distance的倒数(即1-d
)。
您可以使用以下方法计算两个序列之间的反归一化汉明距离:
def inverse_hamming_distance(a,b):
z = list(zip(a, b))
return sum(e[0]==e[1] for e in z) / len(z)
它给出了:
>>> inverse_hamming_distance('CCCCCCCC', 'ACCCACCC')
0.75
但是,您可以通过早期检测两行不类似来节省一些CPU周期。给定最小相似度阈值t
,如果您观察到int(0.5+(1-t)*len(z))
个不同的项目,则不需要直到最后,并且您已经可以告诉项目不相似。
def similar(a,b,t=0.99):
l = min(len(a), len(b))
t = int(0.5 + l*(1 - t))
n = 0
for a1, b1 in zip(a, b):
if a1 != b1:
n += 1
if n > t:
return False
return True
试验:
>>> similar('CCCCCCCC', 'ACCCACCC', 0.75)
True
>>> similar('CCCCCCCC', 'ACCCACCC', 0.9)
False
答案 1 :(得分:2)
首先要加快速度,首先将所有数据存储为整数或二进制列表,然后再进行比较。要么会大大减少比较操作所需的内存。一个可以说是一个很好的选择。执行此操作时,我还会将每个字典值拆分为一个列表,每个项目都是特定样本:basedict = { 'posA' : [samp1, samp2,...] , ... }
。
from enum import Enum
Base = Enum('Base', 'A C T G')
@mescalinum的答案很好地描述了如何使用函数来计算两条线是否相似:
def similar(a,b,t=0.99):
l = min(len(a), len(b))
t = int(0.5 + l*(1 - t))
n = 0
for a1, b1 in zip(a, b):
if a1 != b1:
n += 1
if n > t:
return False
return True
剩下的就是创建一个适用于您的数据集的循环。 similarpositions
列出了每个被认为“相似”的职位的关键字。
similarpositions = []
for key in basedict:
samplecomps = (len(basedict[key]) * (len(basedict[key]) - 1)) / 2 # number of comparisons between samples needed
dissimilar = 0
for item1 in basedict[key]:
for item2 in basedict[key]:
if similar(item1, item2, 0.99) == False:
dissimilar += 1
if samplecomps / dissimilar > 0.01: // break once we know too many dissimilar results, to save unneeded comparisions
break
if samplecomps / dissimilar > 0.01:
break
if samplecomps / dissimilar <= 0.01:
similarpositions.append(key)