【问题标题】:Problems computing cdist of two columns in two different dataframes计算两个不同数据帧中两列 cdist 的问题
【发布时间】:2022-01-12 10:18:53
【问题描述】:

我正在尝试使用来自scipy.spatial.distancecdist 计算两个熊猫数据帧中的向量之间的距离,但输出完全错误,我无法确定失败的位置。

所以,我的原始数据框属于以下类型:

df_sample = 
                                             Fingerprint
1272    [0.0, 4.0, 8.0, 15.0, 10.0, 8.0, 2.54, 2.0, 4.91, 0.0, 0.0, 0.0, 0.0, 3.59, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 8.0]
657    [1.44, 12.0, 10.0, 5.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 8.23, 4.36, 15.0]
806   [4.58, 13.09, 15.46, 3.59, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 6.31]

DF = 
  barcode  \
4538   A4060462000516278   
5043   A4050494272716275   
11663  A4070271111316245   
2701   A4060462848716270   
825    A4060454573516274   
8679   A4060462010016274   
11700  A4060462080916270   
8594   A4060461067716272   
8707   A4060454363916275   
1071   A4060463723916275   

                                                                                                                                    Geopos Ack  
4538     [0.0, 0.0, 0.0, 0.0, 6.0, 15.0, 16.0, 0.0, 0.0, 5.0, 0.0, 15.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 3.0]  
5043   [0.0, 0.0, 0.0, 0.0, 0.0, 16.0, 12.0, 0.0, 13.0, 15.0, 0.0, 15.0, 0.0, 0.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.0, 3.0, 0.0]  
11663      [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.0, 15.0, 0.0, 0.0, 0.0, 6.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]  
2701      [0.0, 0.0, 0.0, 8.0, 13.0, 16.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 6.0, 0.0, 7.0]  
825     [0.0, 0.0, 0.0, 0.0, 0.0, 11.0, 15.0, 0.0, 13.0, 16.0, 0.0, 9.0, 3.0, 0.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]  
8679      [0.0, 4.0, 9.0, 15.0, 10.0, 3.0, 2.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 9.0]  
11700     [0.0, 0.0, 6.0, 0.0, 15.0, 8.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 16.0, 0.0, 6.0]  
8594     [12.0, 16.0, 16.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 5.0]  
8707       [7.0, 5.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 8.0, 15.0]  
1071      [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 12.0, 15.5, 6.0, 3.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]  

(我在问题的末尾提供了这两个字典)。

如您所见,它们具有不同的维度(尽管向量属于同一空间)。因此,为了解决这个问题,我通过这样做在df_sample 中创建了零向量:

Number_AP = 26
number_zero_vectors = len(DF)-len(df_sample)
df =pd.DataFrame(columns = ['Fingerprint'])
for k in range(number_zero_vectors):
    a = zerolistmaker(Number_AP)
    df = df.append({'Fingerprint':a},ignore_index=True)

df_sample_ = pd.concat([df_sample, df])

因此,DFdf_sample_ 具有相同的形状。但是,dtype och df_sample_['Fingerprint']DF['Geopos Ack'] 都是 object,也就是说它们都是列表。所以,我需要把它们做成数组。结果是数组的数组:

Ax = df_sample_['Fingerprint'] = df_sample_['Fingerprint'].apply(lambda x: np.array(x))
Bx = DF['Geopos Ack'] = DF['Geopos Ack'].apply(lambda x: np.array(x))

因此,我需要 1) 将它们制成数组(向量)和 2) 确保它们具有相同的形状以使用 cdist

A = Ax.to_numpy()
B = Bx.to_numpy()
AA = np.concatenate(A, axis=0).reshape(-1,1)
BB = np.concatenate(B, axis=0).reshape(-1,1)

简而言之,我希望计算每对向量 (a, b) 之间的距离,其中 a 是 A 中的向量,b 是 B 中的向量。

例如:

A = [[1, 0], [0, 1]];
B = [[1, 1], [1, 2], [2, 1]];
D = [[1, 2, 2^0.5], [1, 2^0.5, 2]]

因此,为了计算距离,我使用以下完整代码:

import scipy.spatial.distance as sp

Ax = df_sample_['Fingerprint'] = df_sample_['Fingerprint'].apply(lambda x: np.array(x))
Bx = DF['Geopos Ack'] = DF['Geopos Ack'].apply(lambda x: np.array(x))

A = Ax.to_numpy()
B = Bx.to_numpy()
AA = np.concatenate(A, axis=0).reshape(-1,1)
BB = np.concatenate(B, axis=0).reshape(-1,1)


d = sp.cdist(AA,BB, 'euclidean')

但这会返回

array([[0., 0., 0., ..., 0., 0., 0.],
       [4., 4., 4., ..., 4., 4., 4.],
       [8., 8., 8., ..., 8., 8., 8.],
       ...,
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.]])

这是df_sample_中所有数组的串联。

我哪里做错了?我知道另一种方法是使用sklearn 中的pairwise_distance,但我没有设法将其应用于我的数据框。

任何帮助将不胜感激。

数据

df_sample = 
{'Fingerprint': {1272: [0.0,
   4.0,
   8.0,
   15.0,
   10.0,
   8.0,
   2.54,
   2.0,
   4.91,
   0.0,
   0.0,
   0.0,
   0.0,
   3.59,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   2.0,
   8.0],
  657: [1.44,
   12.0,
   10.0,
   5.0,
   6.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   2.0,
   8.23,
   4.36,
   15.0],
  806: [4.58,
   13.09,
   15.46,
   3.59,
   3.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   2.0,
   0.0,
   6.31]}}

DF = 
{'barcode': {4538: 'A4060462000516278',
  5043: 'A4050494272716275',
  11663: 'A4070271111316245',
  2701: 'A4060462848716270',
  825: 'A4060454573516274',
  8679: 'A4060462010016274',
  11700: 'A4060462080916270',
  8594: 'A4060461067716272',
  8707: 'A4060454363916275',
  1071: 'A4060463723916275'},
 'Geopos Ack': {4538: [0.0,
   0.0,
   0.0,
   0.0,
   6.0,
   15.0,
   16.0,
   0.0,
   0.0,
   5.0,
   0.0,
   15.0,
   0.0,
   0.0,
   0.0,
   0.0,
   2.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   3.5,
   0.0,
   3.0],
  5043: [0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   16.0,
   12.0,
   0.0,
   13.0,
   15.0,
   0.0,
   15.0,
   0.0,
   0.0,
   6.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   3.0,
   3.0,
   0.0],
  11663: [0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   5.0,
   15.0,
   0.0,
   0.0,
   0.0,
   6.0,
   2.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0],
  2701: [0.0,
   0.0,
   0.0,
   8.0,
   13.0,
   16.0,
   6.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   6.0,
   0.0,
   7.0],
  825: [0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   11.0,
   15.0,
   0.0,
   13.0,
   16.0,
   0.0,
   9.0,
   3.0,
   0.0,
   6.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0],
  8679: [0.0,
   4.0,
   9.0,
   15.0,
   10.0,
   3.0,
   2.0,
   0.0,
   2.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   2.0,
   9.0],
  11700: [0.0,
   0.0,
   6.0,
   0.0,
   15.0,
   8.0,
   2.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   16.0,
   0.0,
   6.0],
  8594: [12.0,
   16.0,
   16.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   8.0,
   0.0,
   5.0],
  8707: [7.0,
   5.0,
   2.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   2.0,
   8.0,
   15.0],
  1071: [0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   12.0,
   15.5,
   6.0,
   3.5,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0,
   0.0]}}

【问题讨论】:

    标签: python pandas numpy scipy


    【解决方案1】:

    正如scipy.spatial.distance's docs 中提到的,XA 和 XB 应该是您想要找到其中一个到另一个的距离的向量的列表。您在代码中所做的是从所有向量中创建一个长向量,并在我认为您必须做的是堆叠它们时将它们组合起来。虽然您的问题并不清楚您的确切意图,但我可能是错的。

    import pandas as pd
    import numpy as np
    import scipy.spatial.distance as sp
    
    # df_sample and DF are OP's dictionaries
    df_sample_df = pd.DataFrame(df_sample)
    DF_df = pd.DataFrame(DF)
    
    Ax = df_sample_df['Fingerprint'] = df_sample_df['Fingerprint'].apply(lambda x: np.array(x))
    Bx = DF_df['Geopos Ack'] = DF_df['Geopos Ack'].apply(lambda x: np.array(x))
    
    A = Ax.to_numpy()
    B = Bx.to_numpy()
    AA = np.stack(A)
    BB = np.stack(B)
    
    
    d = sp.cdist(AA,BB, 'euclidean')
    print(f'd.shape = {d.shape}')
    print(f'd[0, 0] = {d[0, 0]}')
    print(f'L2(AA[0],BB[0]) = {np.sum((AA[0] - BB[0])**2)**0.5}')
    

    输出:

    d.shape = (3, 10)
    d[0, 0] = 34.57536840006191
    L2(AA[0],BB[0]) = 34.57536840006192
    

    为了使您的问题更清楚,您可以解释要计算的距离是多少,并添加一个 MINIMAL 可重现的示例。 如:

    “我想求每对向量 (a, b) 之间的距离,其中 a 是 A 中的向量,b 是 B 中的向量。
    A = [[1, 0], [0, 1]];
    B = [[1, 1], [1, 2], [2, 1]];
    D = [[1, 2, 2^0.5], [1, 2^0.5, 2]] "

    或者:

    “我想求填充矩阵 A 和矩阵 B 之差的 Frobenius 范数。
    A = [[1, 0], [0, 1]];
    B = [[1, 1], [1, 2], [2, 1]];
    D = 8^0.5 "

    【讨论】:

    • 很好的答案!非常感谢关于如何澄清我的目的的提示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-28
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多