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

复杂逻辑下向量化DataFrame过滤:余弦相似度矩阵指定位置置为np.nan

问题需求

现有一个包含ID列与四个数值列(数值为0至50的整数)的大型DataFrame,需要按ID分组计算余弦相似度矩阵,并对矩阵中满足以下规则的元素设为np.nan:

  • 同一ID分组内,若行1在四个维度上均不劣于行2,且至少有一个维度更优,则矩阵中[1,2]与[2,1]位置的元素需置为np.nan。

示例DataFrame

a   b   c   d   ID
9   9   7   3   1
9   8   3   2   1
6   5   5   6   1
8   4   7   5   1
4   8   7   2   1
4   6   9   5   1
7   4   3   1   1
5   3   5   2   1
8   9   3   9   1
8   2   7   9   1
6   4   1   1   2
3   9   9   3   2
7   6   7   7   2
7   4   9   3   2
2   5   9   2   2
7   6   2   3   2
5   8   7   5   2
6   9   4   1   3
1   6   8   6   3
1   9   7   6   3
2   8   5   4   3
7   2   5   1   3
9   6   5   3   3
8   2   3   2   3
1   8   2   9   3
1   8   1   6   3
3   6   2   4   3
4   2   9   7   3
9   2   6   8   3
1   2   6   3   3

已实现的筛选逻辑

已编写函数筛选符合规则的行索引,代码如下:

def filter_se(row, df, cols = None):
    if cols:
        df = df[cols]
        row = row[cols]
    # 筛选所有列都不劣于当前行的记录
    df = df[(row >= df).all(axis = 1)]
    # 筛选至少有一列更优的记录
    df = df[(row > df).any(axis = 1)]
    indexes = df.index.tolist()
    return indexes

sample_group = sample.groupby("ID")
r = {}
for index, group in sample_group:
    res = group.apply(filter_se, args = [group, ["a", "b", "c", "d"]], axis = 1).tolist()
    
    r[index] = res

筛选结果输出

{1: [[1, 4, 6, 7], [6], [7], [6, 7], [], [], [], [], [6], []],
 2: [[], [14], [10, 15], [10], [], [10], []],
 3: [[],
  [29],
  [25, 29],
  [],
  [],
  [21, 23],
  [],
  [25],
  [],
  [],
  [29],
  [21, 23, 29],
  []]}

余弦相似度矩阵计算

已通过以下代码计算各ID对应的余弦相似度矩阵,得到以ID为索引、相似度矩阵为值的pd.Series对象:

from sklearn.metrics.pairwise import cosine_similarity

sims = sample.groupby("ID").apply(lambda g: cosine_similarity(g[["a", "b", "c", "d"]]))

当前问题

无法将相似度矩阵中符合规则的指定位置元素置为np.nan,需要完成此操作。


解决方案

可以通过遍历每个ID对应的相似度矩阵和筛选结果,直接修改矩阵中的对应位置为np.nan,同时处理双向位置:

import numpy as np

# 遍历每个ID的相似度矩阵和筛选结果
for id_val in r.keys():
    sim_matrix = sims.loc[id_val]
    filter_list = r[id_val]
    n_rows = sim_matrix.shape[0]
    
    # 遍历每一行的索引和对应的需置nan的列索引
    for i in range(n_rows):
        cols_to_nan = filter_list[i]
        # 将[i, col]和[col, i]位置设为nan
        for col in cols_to_nan:
            sim_matrix[i, col] = np.nan
            sim_matrix[col, i] = np.nan
    
    # 更新sims中的矩阵
    sims.loc[id_val] = sim_matrix

解释

  1. 遍历每个ID,取出对应的相似度矩阵和筛选得到的索引列表
  2. 对每一行i,获取所有需要置为np.nan的列索引cols_to_nan
  3. 分别将矩阵的[i, col]和[col, i]位置设为np.nan
  4. 更新原pd.Series中的矩阵

如果需要避免原地修改,可以先创建矩阵的副本再操作:

for id_val in r.keys():
    sim_matrix = sims.loc[id_val].copy()
    filter_list = r[id_val]
    n_rows = sim_matrix.shape[0]
    
    for i in range(n_rows):
        cols_to_nan = filter_list[i]
        for col in cols_to_nan:
            sim_matrix[i, col] = np.nan
            sim_matrix[col, i] = np.nan
    
    sims.loc[id_val] = sim_matrix

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 16:11:15