You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Smith-Waterman算法计算序列相似度并生成相似分组排名DataFrame

解决方法:计算序列间Smith-Waterman相似度并生成排名结果

首先要确认你已经定义了sub_cost函数(你的smith_waterman依赖这个但未给出实现),下面是一个通用的替换成本示例,你可以根据需求调整匹配/不匹配的分值:

import numpy as np
import pandas as pd
from itertools import combinations

# 定义替换成本函数:匹配得2分,不匹配扣1分
def sub_cost(a, b):
    return 2 if a == b else -1

# 保留你提供的Smith-Waterman函数
def smith_waterman(seq2, seq1, d=-8):
    m = len(seq1)
    n = len(seq2)
    mat = np.zeros((m+1, n+1)) # 创建空矩阵
    # 填充矩阵
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            diag = mat[i-1][j-1] + sub_cost(seq1[i-1], seq2[j-1])
            up = mat[i-1][j] + d
            left = mat[i][j-1] + d
            mat[i][j] = max(0, diag, up, left)
    # 找到矩阵中的最高分位置
    highest_value = np.where(mat == np.amax(mat))
    highest_value_location = list(zip(highest_value[0], highest_value[1]))[0]
    traceback_seq1, traceback_seq2 = '', ''
    i, j = highest_value_location[0], highest_value_location[1]
    # 回溯生成比对序列(此处我们只需要最高分,所以回溯部分不影响最终返回值)
    while i > 0 or j > 0:
        current_score = mat[i][j]
        diag_score = mat[i-1][j-1]
        left_score = mat[i][j-1]
        up_score = mat[i-1][j]
        if (current_score==0):
            break
        if (current_score == diag_score + sub_cost(seq1[i-1], seq2[j-1])):
            t1, t2 = seq2[j-1], seq1[i-1]
            i,j = i-1,j-1
        elif (current_score == up_score + d):
            t1, t2 = '-', seq1[i-1]
            i -= 1
        elif (current_score == left_score + d):
            t1, t2 = seq2[j-1], '-'
            j -= 1
        traceback_seq1 += t1
        traceback_seq2 += t2
    traceback_seq1 = (traceback_seq1[::-1])
    traceback_seq2 = (traceback_seq2[::-1])
    return np.amax(mat)

步骤1:生成所有唯一的变体对

我们用itertools.combinations生成不重复的变体组合(避免重复计算A vs B和B vs A,因为Smith-Waterman得分是对称的):

# 基于你的DataFrame生成所有两两变体对
variant_pairs = list(combinations(finalDF['Variant ID'], 2))

步骤2:批量计算相似度得分

遍历每个变体对,提取对应序列并计算Smith-Waterman得分:

# 初始化结果存储列表
results = []

for var1, var2 in variant_pairs:
    # 根据Variant ID获取对应的序列
    seq1 = finalDF.loc[finalDF['Variant ID'] == var1, 'original_sequence'].iloc[0]
    seq2 = finalDF.loc[finalDF['Variant ID'] == var2, 'original_sequence'].iloc[0]
    # 计算相似度得分
    sim_score = smith_waterman(seq1, seq2)
    # 将结果存入列表
    results.append({
        'Variants': f"{var1} & {var2}",
        'Similarity': sim_score
    })

步骤3:生成带排名的结果DataFrame

将结果转换为DataFrame,按相似度降序排序并添加排名列:

# 转换为DataFrame
result_df = pd.DataFrame(results)

# 按相似度降序排序,添加排名(相同得分将获得相同排名)
result_df = result_df.sort_values(by='Similarity', ascending=False)
result_df['RANK'] = result_df['Similarity'].rank(method='min', ascending=False).astype(int)

# 查看前5条结果
print(result_df.head())

优化提示(针对大数量序列)

如果你的DataFrame包含成百上千个变体,上述方法会因Smith-Waterman的O(mn)复杂度变慢,可以尝试:

  • 用joblib库实现并行计算,加速遍历过程
  • 先过滤长度差异极大的序列对,减少不必要的计算

内容的提问来源于stack exchange,提问作者Varsha Gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:55:55