我有一个数据帧,看起来像这样:
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. ]])