一尘不染

具有复杂逻辑的矢量化数据帧过滤

py

我有一个非常大的数据框,有五列,ID 和四个数字。比方说,0 到 50 之间的整数。我的目标是为每个 ID 计算余弦相似度矩阵。

但是,我想将某些矩阵值强制为np.nan. 也就是说,如果在给定的 ID 中,一行(比如说 1)在所有四个维度上都不比另一行(比如说 2)差,同时至少在一个维度上更好,那么坐标 [1, 2] 和[2, 1] 必须设置为np.nan

示例数据框:

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]
    #filter for all rows where none of the columns are worse
    df = df[(row >= df).all(axis = 1)]
    #filter for rows where any column is better.
    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

Output: r
{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 的相似度矩阵:

from sklearn.metrics.pairwise import cosine_similarity

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

这给了我一个pd.Series相似矩阵是值和 ID 是索引的对象。下一步是设置np.nan我正在努力处理的矩阵的元素。我想寻求帮助。


阅读 98

收藏
2023-01-31

共1个答案

一尘不染

这是具有给定 ID 的组的可能解决方案。在通用设置中,它可以应用于每个 ID 组。df是带有数据的数据框。

import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

# select the group with a specified ID and convert it into a numpy array
ID = 1
arr = df[df["ID"] == ID][["a", "b", "c", "d"]].to_numpy()

# compute the similarity matrix for this group
b = arr[..., None]
c = arr.T[None, ...]
mask = (((b >= c).all(axis=1)) & ((b > c).any(axis=1)))
mask |= mask.T
sims = np.where(mask, np.nan, cosine_similarity(arr))
2023-01-31