2017-10-07 35 views
2

恢復這個問題Compute the pairwise distance in scipy with missing values如何有效地計算一系列不同長度(na內)之間的成對距離?

測試用例:我想計算不同長度taht一系列成對距離被組合在一起,我必須這樣做最有效的可行方法(使用歐氏距離)。這使得它的工作可能是這個

一個辦法:

import pandas as pd 
import numpy as np 
from scipy.spatial.distance import pdist 

a = pd.DataFrame(np.random.rand(10, 4), columns=['a','b','c','d']) 
a.loc[0, 'a'] = np.nan 
a.loc[1, 'a'] = np.nan 
a.loc[0, 'c'] = np.nan 
a.loc[1, 'c'] = np.nan 

def dropna_on_the_fly(x, y): 
    return np.sqrt(np.nansum(((x-y)**2))) 

pdist(starting_set, dropna_on_the_fly) 

,但我覺得建在pdist功能的方法是內部優化,而功能簡單地越過這可能是非常低效的。

我有一種預感,在numpy一個量化的解決方案,這是我broadcast減法,然後我繼續進行np.nansumna耐總和,但我對如何進行把握。

回答

3

this post的啓發,會有兩種解決方案。

方法#1:矢量化的解決辦法是 -

ar = a.values 
r,c = np.triu_indices(ar.shape[0],1) 
out = np.sqrt(np.nansum((ar[r] - ar[c])**2,1)) 

方法2:存儲器效率和更高性能的一個大的陣列將是 -

ar = a.values 
b = np.where(np.isnan(ar),0,ar) 

mask = ~np.isnan(ar) 
n = b.shape[0] 
N = n*(n-1)//2 
idx = np.concatenate(([0], np.arange(n-1,0,-1).cumsum())) 
start, stop = idx[:-1], idx[1:] 
out = np.empty((N),dtype=b.dtype) 
for j,i in enumerate(range(n-1)): 
    dif = b[i,None] - b[i+1:] 
    mask_j = (mask[i] & mask[i+1:]) 
    masked_vals = mask_j * dif 
    out[start[j]:stop[j]] = np.einsum('ij,ij->i',masked_vals, masked_vals) 
     # or simply : ((mask_j * dif)**2).sum(1) 

out = np.sqrt(out) 
+0

如平常,非常感謝 – Asher11

相關問題