使用自定义相似性函数创建距离矩阵



我有一个数据帧,看起来像这样:

data = pd.DataFrame({'id':[1,1,1,2,2,2,3,3,3],
'age':[20, 21,18,54,23,11, 19, 18,12],
'experience':[5,4,3,8,2,11,2,8,6]},columns=['id','age','experience'])
id  age experience
0   1   20  5
1   1   21  4
2   1   18  3
3   2   54  8
4   2   23  2
5   2   11  11
6   3   19  2
7   3   18  8
8   3   12  6

我正在使用一个名为dtw_path的自定义距离函数,它计算元组之间的距离。我不打算讨论这个函数是如何计算距离的,因为它是一个复杂的过程,但它只是输出元组之间的标量距离值。

元组以以下方式形成:

data['age_exp'] = data[['age', 'experience']].apply(tuple, axis=1)
id  age experience  age_exp
0   1   20   5          (20, 5)
1   1   21   4          (21, 4)
2   1   18   3          (18, 3)
3   2   54   8          (54, 8)
4   2   23   2          (23, 2)
5   2   11   11         (11, 11)
6   3   19   2          (19, 2)
7   3   18   8          (18, 8)
8   3   12   6          (12, 6)

因此,对于上面的数据帧,如果我需要计算id 1和id 2之间的距离,我会计算如下距离:

data1 = data[data['id']==1]
data1 = np.array(data1['age_exp'].tolist())
data1
array([[20,  5],
[21,  4],
[18,  3]])
data2 = data[data['id']==2]
data2 = np.array(data2['age_exp'].tolist())
data2
array([[54,  8],
[23,  2],
[11, 11]])
dtw_path(data1,data2)[1]
1.5

我需要帮助的是如何在数据帧中循环并为id列创建距离矩阵,即类似于的东西

1    2     3
1    0    1.5   2          
2    1.5  0     2.3
3    2    2.3   0

您的问题中不清楚dtw_path是什么。我在这里使用了tslearn.metrics.dtw_path,这给了我不同的结果。然而,理由应该是相同的。

让我们首先对原始数据帧进行一点整形:

data2 = (data.groupby('id')
.apply(lambda x: np.array(list(zip(x['age'], x['experience']))))
).to_frame()
0
id                              
1    [[20, 5], [21, 4], [18, 3]]
2   [[54, 8], [23, 2], [11, 11]]
3    [[19, 2], [18, 8], [12, 6]]

注:。下一步需要是二维的(DataFrame(,因此.to_frame()

然后,使用scipy.spatial.distance.pdist应用dtw_path函数,该函数可以使用参数metric获取任意距离函数,并且只保留输出的第二个元素。最后,使用scipy.spatial.distance.squareform:将输出重塑为方形矩阵

squareform(pdist(data2, metric=lambda x,y: dtw_path(x[0], y[0])[1]))

输出:

array([[ 0.        , 35.86084215,  8.94427191],
[35.86084215,  0.        , 36.7151195 ],
[ 8.94427191, 36.7151195 ,  0.        ]])

最新更新