我有一个非常大的数据框,有五列,ID 和四个数字。比方说,0 到 50 之间的整数。我的目标是为每个 ID 计算余弦相似度矩阵。
但是,我想将某些矩阵值强制为np.nan. 也就是说,如果在给定的 ID 中,一行(比如说 1)在所有四个维度上都不比另一行(比如说 2)差,同时至少在一个维度上更好,那么坐标 [1, 2] 和[2, 1] 必须设置为np.nan。
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我正在努力处理的矩阵的元素。我想寻求帮助。
pd.Series
这是具有给定 ID 的组的可能解决方案。在通用设置中,它可以应用于每个 ID 组。df是带有数据的数据框。
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))