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

如何在Python中找到与目标分子最匹配的分子(非数值数据)

非数值分子相互作用数据的匹配实现方案

问题背景

现有一张记录分子与氨基酸残基相互作用类型的表格,第一行为目标分子,需要从其余行中找到与目标分子相互作用模式最相似的分子。此前处理数值数据时使用scipy.spatial.distance.cdist的相关系数,但当前数据为多类型字符串(如"Pi-Si, Pi-Al")和空值,无法直接套用数值方法。

核心思路

需要先将非数值的相互作用类型转换为可计算的结构,再通过自定义相似度/距离函数衡量匹配度:

  • 数据结构化:把每个单元格的多类型字符串拆分为集合(方便后续集合运算),空值转为空集合。
  • 选择匹配逻辑:针对集合类型数据,优先用Jaccard相似度(交集元素数/并集元素数)衡量单个位点的匹配度,再将所有位点的得分求和/平均得到整体相似度;也可根据业务需求定义加权得分(比如完全匹配得1分,部分重叠得0.5分,无重叠得0分)。
  • 计算并筛选:用自定义函数计算所有分子与目标分子的相似度,取得分最高的分子。

具体实现代码

步骤1:加载并预处理数据

假设表格已读取为pandas.DataFrame,先做结构化转换:

import pandas as pd

# 假设数据已读取到df中,第一行是目标分子
target = df.iloc[0]
candidates = df.iloc[1:]

# 定义预处理函数:将单元格内容转为集合
def process_cell(cell):
    if pd.isna(cell) or cell == "":
        return set()
    # 去除引号,拆分类型,转集合
    clean_cell = cell.strip('"').strip()
    return set([t.strip() for t in clean_cell.split(',')])

# 对整个DataFrame应用预处理
processed_df = df.applymap(process_cell)
processed_target = processed_df.iloc[0]
processed_candidates = processed_df.iloc[1:]

步骤2:定义相似度计算函数

这里用Jaccard相似度的均值作为整体匹配得分:

def calculate_similarity(row, target):
    scores = []
    for col in row.index:
        row_set = row[col]
        target_set = target[col]
        # 计算Jaccard相似度:交集/并集,避免除以0
        union = len(row_set.union(target_set))
        if union == 0:
            scores.append(1.0)  # 两个都是空集合,视为完全匹配
        else:
            scores.append(len(row_set.intersection(target_set)) / union)
    # 返回平均得分
    return sum(scores) / len(scores)

步骤3:计算并找到最匹配的分子

# 计算所有候选分子的相似度
candidates['similarity'] = processed_candidates.apply(calculate_similarity, target=processed_target, axis=1)

# 找到相似度最高的分子
most_similar = candidates[candidates['similarity'] == candidates['similarity'].max()]

print("最匹配的分子:")
print(most_similar)

可选优化

  • 加权匹配:如果某些氨基酸残基的相互作用更重要,可以给对应位点的得分加权重:
    # 定义权重字典,比如Met1160权重为2,其他为1
    weights = {col: 2 if col == 'Met1160' else 1 for col in processed_target.index}
    # 修改相似度计算函数,加权求和
    weighted_sum = sum(score * weights[col] for score, col in zip(scores, row.index))
    return weighted_sum / sum(weights.values())
    
  • 严格匹配:如果需要严格匹配(只有当两个位点的相互作用类型完全一致时得分1,否则0),可替换Jaccard计算逻辑:
    scores.append(1.0 if row_set == target_set else 0.0)
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 06:00:59