我正在尝试在 pandas 数据帧上应用成对欧几里德距离计算的变体来生成边缘列表。
标准欧式距离计算可以是:
from scipy.spatial.distance import pdist
from scipy.spatial.distance import squareform
import pandas as pd
import numpy as np
# after dataframe is loaded
d_array = pdist(df, 'euclidean')
d_df = pd.DataFrame(squareform(d_array), index=df.index, columns= df.index)
d_df = d_df.where(np.triu(np.ones(d_df.shape)).astype(np.bool))
edge_list = d_df.stack()
我做了欧几里得距离计算的变体:
from math import *
import itertools
def arc_sub(a, b):
HALF_CIRCUM = 180
l = max(a, b)
s = min(a, b)
if l - s > HALF_CIRCUM:
return s + HALF_CIRCUM * 2 - l
else:
return l - s
def arc_dist(df, pair):
df_pair = df.loc[pair, :]
x = df_pair.loc[pair[0], :]
y = df_pair.loc[pair[1], ]
return sqrt(sum(pow(arc_sub(a, b), 2) for a, b in zip(x, y)))
pairs = list(itertools.combinations(list(df.index), 2))
edge_list = pd.DataFrame([arc_dist(df, pair) for pair in pairs], index=pairs)
似乎我的变化比pdist
of慢得多,scipy
我猜这是由于循环通过配对列表。它占用的内存比pdist
我猜想pdist
一次将计算应用于所有对。有什么方法可以将我的距离计算也应用于所有对吗?