我在Python中有一对等长字符串,以及一个可接受的字母表。并非字符串中的所有字母都来自接受的字母表。 E.g。
str1 = 'ACGT-N?A'
str2 = 'AAGAA??T'
alphabet = 'ACGT'
我想得到的是numpy
矩阵,它描述了字符串之间的相似点和不同点。即矩阵的列是str1
中接受的字母表中的字母,行是str2
中接受的字母表中的字母。条目是str1
和str2
包含相关字母的次数的总和。我只关心两个字符串在给定位置接受字母的情况。
因此,对于上面的示例,我的输出将是(cols为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-by-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
答案 0 :(得分:2)
使用布尔矩阵的点积(保持秩序正确的最简单方法):
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]])
答案 1 :(得分:1)
此任务可以使用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