2017-08-03 50 views
1

我正在计算两个距离并在二维数组中以0.1的间隔对它们进行合并。目前我正在这样做。然而,大量点需要很多时间将数据合并到二维数组中

import numpy as np 
from scipy.spatial import distance as d 
dat=np.random.rand(100,3) 
dd2d=np.zeros((10,10)) 
while len(dat)>0: 
    i=len(dat)-1 
    while i>0: 
     dist0=d.euclidean(dat[0],dat[i]) 
     dist1=d.cosine(dat[0],dat[i]) 
     ind0=int(dist0/0.1) 
     ind1=int(dist1/0.1) 
     if ind0>9 or ind1>9: 
      pass 
     else: 
      dd2d[ind0,ind1]+=1 
     i-=1 
    dat=np.delete(dat,0,axis=0) 
    print len(dat) 

这样做的最有效的方法是什么?

另外我该如何将我的代码中的while循环转换为for循环,以便我可以添加progressbar/tqdm来跟踪运行时间。

+1

如果你的目标是速度,不要使用'while'循环。不要使用'for'循环。不要这样做 - “dist0/0.1” - 分割比乘法更慢。做'dist0 * 10'。你想要的是将你的循环向量化成编译C代码的东西。类似'pdist' –

+0

我正在使用cython编写的另一个函数来计算距离。所以这部分是优化的。这里给出'scipy.spatial.distance'仅用于说明目的 –

+1

应该仍然可以使用'pdist(dat,lambda u,v:myUFunc(u,v))'。虽然如果你的距离函数是矢量化的,你也可以做'dist0 = myUFunc(dat [i],dat [j])' –

回答

2

如果您已经导入scipy.spatial.distance,不妨使用pdist。然后你只是制作一个2D直方图。使用np.histogram2d

def binDists2d(dat, f1 = 'euclidean', f2 = 'cosine'): 
    dist0 = d.pdist(dat, f1) 
    dist1 = d.pdist(dat, f2) 
    rng = np.array([[0, 1], [0, 1]]) 
    return np.histogram2d(dist0, dist1, bins = 10, range = rng) 

pdist只返回上三角形元素。如果您想手动执行此操作,请使用np.triu_indices,如果scipy不可用,您可以使用它来生成距离。

def cosdist(u, v): 
    return 1 - u.dot(v)/(np.linalg.norm(u) * np.linlg.norm(v)) 

def binDists2d(dat, f0 = lambda u, v: np.linalg.norm(u - v), f1 = cosdist): 
    i, j = np.triu_indices(dat.shape[0], 1) 
    dist0 = f0(dat[i], dat[j]) 
    dist1 = f1(dat[i], dat[j]) 
    rng = np.array([[0, 1], [0, 1]]) 
    return np.histogram2d(dist0, dist1, bins = 10, range = rng) 

编辑:少消耗内存的版本:

def binDists2d(dat, f0, f1, n = 1, bins = 10, rng = np.array([[0, 1], [0, 1]])): 
    i_, j_ = np.triu_indices(dat.shape[0], 1) 
    out = np.zeros((bins, bins)) 
    i_, j_ = np.array_split(i_, n), np.array_split(j_, n) 
    for k, (i, j) in enumerate(zip(i_, j_)): 
     dist0 = f0(dat[i], dat[j]) 
     dist1 = f1(dat[i], dat[j]) 
     out += np.histogram2d(dist0, dist1, bins = bins, range = rng) 
     print(str(k) + " of " + str(n) + "completed") 
    return out 
+0

'--------------------- -------------------------------------------------- ---- IndexError回溯(最近最后调用) () ----> 1 binDists2d(DAT) 在binDists2d(dat,f1,f2) 3 dist1 = d.pdist(dat,f2) 4 i,j = np.triu_indices(dat.shape [0],1) ----> 5 return np.histogram2d (dist0 [i,j],dist1 [i,j],bin = 10) IndexError:索引太多array' –

+0

我得到Indexerror for'dat = np.random.rand(10,3)'runnin g用'binDists2d'函数给出 –

+1

哎呀,现在'pdist'输出上三角。这很方便。 –