从 Python 中的等长字符串计算 similarity/difference 矩阵
Calculating a similarity/difference matrix from equal length strings in Python
我在 Python 中有成对的等长字符串和一个可接受的字母表。并非字符串中的所有字母都来自公认的字母表。例如
str1 = 'ACGT-N?A'
str2 = 'AAGAA??T'
alphabet = 'ACGT'
我要得到的是一个numpy
矩阵,描述了字符串之间的异同。 IE。矩阵的列是 str1
中接受的字母表中的字母,行是 str2
中接受的字母表中的字母。这些条目是 str1
和 str2
包含相关字母的次数的总和。我只关心两个字符串都在给定位置接受字母的情况。
因此,对于上面的示例,我的输出将是(列为 str1
,行为 str2
,名称按字母顺序从左上角开始):
# cols & rows both refer to 'A', 'C', 'G', 'T' starting top left
# cols are str1, rows are str2
array([[ 1, 1, 0, 1],
[ 0, 0, 0, 0],
[ 0, 0, 1, 0],
[ 1, 0, 0, 0]])
我可以通过遍历每对可能的解决方案来强行解决这个问题,但我想知道是否有人对更通用的解决方案有提示(或链接)。例如。有没有一种方法可以更接近我可以定义 N 个唯一字符的字母表,并在给定两个等长输入字符串的情况下得到一个 N×N 矩阵?
蛮力方法:
def matrix(s1,s2):
m= np.zeros((4,4))
for i in range(len(s1)):
if s1[i]==s2[i]:
if s1[i]=="A":
m[0,0]=m[0,0]+1
elif s1[i]=="C":
m[1,1]=m[1,1]+1
elif s1[i]=="G":
m[2,2]=m[2,2]+1
elif s1[i]=="T":
m[3,3]=m[3,3]+1
elif s1[i]=="A":
if s2[i]=="C":
m[1,0]=m[1,0]+1
elif s2[i]=="G":
m[2,0]=m[2,0]+1
elif s2[i]=="T":
m[3,0]=m[3,0]+1
elif s1[i]=="C":
if s2[i]=="A":
m[0,1]=m[0,1]+1
elif s2[i]=="G":
m[2,1]=m[2,1]+1
elif s2[i]=="T":
m[3,1]=m[3,1]+1
elif s1[i]=="G":
if s2[i]=="A":
m[0,2]=m[0,2]+1
elif s2[i]=="C":
m[1,2]=m[1,2]+1
elif s2[i]=="T":
m[3,2]=m[3,2]+1
elif s1[i]=="T":
if s2[i]=="C":
m[1,3]=m[1,3]+1
elif s2[i]=="G":
m[2,3]=m[2,3]+1
elif s2[i]=="A":
m[0,3]=m[0,3]+1
return m
使用 set
、一些理解和 pandas.DataFrame
可以简洁地完成此任务:
代码:
from collections import Counter
import pandas as pd
def dot_product(allowed, s1, s2):
in_s1 = {c: set([y.start() for y in [
x for x in re.finditer(c, s1)]]) for c in allowed}
in_s2 = {c: set([y.start() for y in [
x for x in re.finditer(c, s2)]]) for c in allowed}
return pd.DataFrame(
[[len(in_s1[c1] & in_s2[c2]) for c1 in allowed] for c2 in allowed],
columns=list(allowed),
index=list(allowed),
)
测试代码:
str1 = 'ACGT-N?A'
str2 = 'AAGAA??T'
alphabet = 'ACGT'
print(dot_product_sum(alphabet, str1, str2))
结果:
A C G T
A 1 1 0 1
C 0 0 0 0
G 0 0 1 0
T 1 0 0 0
使用布尔矩阵的点积(保持顺序正确的最简单方法):
def simMtx(a, x, y):
a = np.array(list(a))
x = np.array(list(x))
y = np.array(list(y))
ax = (x[:, None] == a[None, :]).astype(int)
ay = (y[:, None] == a[None, :]).astype(int)
return np.dot(ay.T, ax)
simMtx(alphabet, str1, str2)
Out[183]:
array([[1, 1, 0, 1],
[0, 0, 0, 0],
[0, 0, 1, 0],
[1, 0, 0, 0]])
我在 Python 中有成对的等长字符串和一个可接受的字母表。并非字符串中的所有字母都来自公认的字母表。例如
str1 = 'ACGT-N?A'
str2 = 'AAGAA??T'
alphabet = 'ACGT'
我要得到的是一个numpy
矩阵,描述了字符串之间的异同。 IE。矩阵的列是 str1
中接受的字母表中的字母,行是 str2
中接受的字母表中的字母。这些条目是 str1
和 str2
包含相关字母的次数的总和。我只关心两个字符串都在给定位置接受字母的情况。
因此,对于上面的示例,我的输出将是(列为 str1
,行为 str2
,名称按字母顺序从左上角开始):
# cols & rows both refer to 'A', 'C', 'G', 'T' starting top left
# cols are str1, rows are str2
array([[ 1, 1, 0, 1],
[ 0, 0, 0, 0],
[ 0, 0, 1, 0],
[ 1, 0, 0, 0]])
我可以通过遍历每对可能的解决方案来强行解决这个问题,但我想知道是否有人对更通用的解决方案有提示(或链接)。例如。有没有一种方法可以更接近我可以定义 N 个唯一字符的字母表,并在给定两个等长输入字符串的情况下得到一个 N×N 矩阵?
蛮力方法:
def matrix(s1,s2):
m= np.zeros((4,4))
for i in range(len(s1)):
if s1[i]==s2[i]:
if s1[i]=="A":
m[0,0]=m[0,0]+1
elif s1[i]=="C":
m[1,1]=m[1,1]+1
elif s1[i]=="G":
m[2,2]=m[2,2]+1
elif s1[i]=="T":
m[3,3]=m[3,3]+1
elif s1[i]=="A":
if s2[i]=="C":
m[1,0]=m[1,0]+1
elif s2[i]=="G":
m[2,0]=m[2,0]+1
elif s2[i]=="T":
m[3,0]=m[3,0]+1
elif s1[i]=="C":
if s2[i]=="A":
m[0,1]=m[0,1]+1
elif s2[i]=="G":
m[2,1]=m[2,1]+1
elif s2[i]=="T":
m[3,1]=m[3,1]+1
elif s1[i]=="G":
if s2[i]=="A":
m[0,2]=m[0,2]+1
elif s2[i]=="C":
m[1,2]=m[1,2]+1
elif s2[i]=="T":
m[3,2]=m[3,2]+1
elif s1[i]=="T":
if s2[i]=="C":
m[1,3]=m[1,3]+1
elif s2[i]=="G":
m[2,3]=m[2,3]+1
elif s2[i]=="A":
m[0,3]=m[0,3]+1
return m
使用 set
、一些理解和 pandas.DataFrame
可以简洁地完成此任务:
代码:
from collections import Counter
import pandas as pd
def dot_product(allowed, s1, s2):
in_s1 = {c: set([y.start() for y in [
x for x in re.finditer(c, s1)]]) for c in allowed}
in_s2 = {c: set([y.start() for y in [
x for x in re.finditer(c, s2)]]) for c in allowed}
return pd.DataFrame(
[[len(in_s1[c1] & in_s2[c2]) for c1 in allowed] for c2 in allowed],
columns=list(allowed),
index=list(allowed),
)
测试代码:
str1 = 'ACGT-N?A'
str2 = 'AAGAA??T'
alphabet = 'ACGT'
print(dot_product_sum(alphabet, str1, str2))
结果:
A C G T
A 1 1 0 1
C 0 0 0 0
G 0 0 1 0
T 1 0 0 0
使用布尔矩阵的点积(保持顺序正确的最简单方法):
def simMtx(a, x, y):
a = np.array(list(a))
x = np.array(list(x))
y = np.array(list(y))
ax = (x[:, None] == a[None, :]).astype(int)
ay = (y[:, None] == a[None, :]).astype(int)
return np.dot(ay.T, ax)
simMtx(alphabet, str1, str2)
Out[183]:
array([[1, 1, 0, 1],
[0, 0, 0, 0],
[0, 0, 1, 0],
[1, 0, 0, 0]])