【问题标题】:binning data live into a 2D array将数据实时合并到二维数组中
【发布时间】:2017-08-03 06:44:42
【问题描述】:

我正在计算两个距离,并在二维数组中以 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 循环,以便我可以添加进度条/tqdm 来跟踪运行时间。

【问题讨论】:

  • 如果您的目标是速度,请不要使用while 循环。不要使用for 循环。不要这样做——dist0/0.1——除法比乘法慢得多。做dist0 * 10。你想要的是将你的循环向量化为在编译 C 代码中运行的东西。类似pdist
  • 我正在使用用 cython 编写的不同函数来计算距离。所以这部分是优化的。这里给出scipy.spatial.distance 仅用于说明目的
  • 应该仍然可以使用pdist(dat, lambda u, v: myUFunc(u,v))。虽然如果你的距离函数是矢量化的,你也可以做dist0 = myUFunc(dat[i], dat[j])

标签: python arrays numpy binning


【解决方案1】:

如果您已经在导入scipy.spatial.distance,不妨使用pdist。然后你只是制作一个二维直方图。使用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

【讨论】:

  • --------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-238-f81d36e3b407> in <module>() ----> 1 binDists2d(dat) <ipython-input-237-b9685d10b4d4> in 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], bins = 10) IndexError: too many indices for array
  • 我得到 Indexerror for dat=np.random.rand(10,3) running with binDists2dfunction you given
  • 哎呀,pdist 现在本机输出上三角。这很方便。
  • 现在它可以工作并且速度也很快......我将在我的主要数据上进行测试并报告......现在我接受这个作为答案。虽然我无法跟踪这个功能取得了多少进展......对于高没有。数据点(我有大约 0.1M)可能需要很多时间来执行
  • 如果您的 RAM 超载,请查看 np.memmap 并尝试将 dist 数组写入磁盘,然后从可管理大小的距离数据块创建一组 histogram2d 输出你可以在最后总结一下。
猜你喜欢
  • 1970-01-01
  • 2019-05-05
  • 1970-01-01
  • 2018-02-09
  • 2021-10-18
  • 2021-10-21
  • 1970-01-01
  • 2014-03-12
  • 2021-11-17
相关资源
最近更新 更多