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

Create distance matrix using a custom similarity function

我有一个如下所示的数据框:

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 that can take an arbitrary distance function using the parameter metric and keep only the second element of the output. Finally, reshape the output as a square matrix using scipy.spatial.distance.squareform:

应用您的 dtw_path 函数
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.        ]])