我们可以执行
dimensionality-reduction简化
cubes为一维数组。这是基于将给定的多维数据集数据映射到n维网格上以计算线性索引等效项的方法,该方法将详细讨论here。然后,基于这些线性索引的唯一性,我们可以分离唯一组及其对应的索引。因此,按照这些策略,我们将有一个解决方案,像这样-
N = 4 # number of indices per groupc1D = np.ravel_multi_index(cubes.T, cubes.max(0)+1)sidx = c1D.argsort()indices = sidx.reshape(-1,N)unq_groups = cubes[indices[:,0]]# If you need in a zipped dictionary formatout = dict(zip(map(tuple,unq_groups), indices))
备选方案1: 如果in
cubes中的整数太大,则可能要这样做
dimensionality-reduction,以选择范围较小的尺寸作为主轴。因此,对于这些情况,我们可以将缩减步骤修改为get
c1D,如下所示:
方法#2s1,s2 = cubes[:,:2].max(0)+1s = np.r_[s2,1,s1*s2]c1D = cubes.dot(s)
接下来,我们可以使用
Cython-powered kd-tree快速最近邻查找来获取最近邻索引,从而像这样解决我们的情况-
from scipy.spatial import cKDTreeidx = cKDTree(cubes).query(cubes, k=N)[1] # N = 4 as discussed earlierI = idx[:,0].argsort().reshape(-1,N)[:,0]unq_groups,indices = cubes[I],idx[I]
一般情况:每组索引数量可变
我们将对基于argsort的方法进行一些扩展以得到所需的输出,如下所示:
c1D = np.ravel_multi_index(cubes.T, cubes.max(0)+1)sidx = c1D.argsort()c1Ds = c1D[sidx]split_idx = np.flatnonzero(np.r_[True,c1Ds[:-1]!=c1Ds[1:],True])grps = cubes[sidx[split_idx[:-1]]]indices = [sidx[i:j] for (i,j) in zip(split_idx[:-1],split_idx[1:])]# If needed as dict o/pout = dict(zip(map(tuple,grps), indices))
使用1D版本的组cubes
作为键
我们将使用
cubesas键组扩展先前列出的方法,以简化字典创建过程并使其高效使用,例如-
def numpy1(cubes): c1D = np.ravel_multi_index(cubes.T, cubes.max(0)+1) sidx = c1D.argsort() c1Ds = c1D[sidx] mask = np.r_[True,c1Ds[:-1]!=c1Ds[1:],True] split_idx = np.flatnonzero(mask) indices = [sidx[i:j] for (i,j) in zip(split_idx[:-1],split_idx[1:])] out = dict(zip(c1Ds[mask[:-1]],indices)) return out
接下来,我们将使用
numbapackage进行迭代并获得最终的可哈希字典输出。随之而来的是,有两种解决方案-
一种使用键和值分别获取,
numba主调用将压缩并转换为dict,而另一种将创建
numba-supporteddict类型,因此主调用函数不需要额外的工作。
因此,我们将有第一个
numba解决方案:
from numba import njit@njitdef _numba1(sidx, c1D): out = [] n = len(sidx) start = 0 grpID = [] for i in range(1,n): if c1D[sidx[i]]!=c1D[sidx[i-1]]: out.append(sidx[start:i]) grpID.append(c1D[sidx[start]]) start = i out.append(sidx[start:]) grpID.append(c1D[sidx[start]]) return grpID,outdef numba1(cubes): c1D = np.ravel_multi_index(cubes.T, cubes.max(0)+1) sidx = c1D.argsort() out = dict(zip(*_numba1(sidx, c1D))) return out
第二种
numba解决方案是:
from numba import typesfrom numba.typed import Dictint_array = types.int64[:]@njitdef _numba2(sidx, c1D): n = len(sidx) start = 0 outt = Dict.empty( key_type=types.int64, value_type=int_array, ) for i in range(1,n): if c1D[sidx[i]]!=c1D[sidx[i-1]]: outt[c1D[sidx[start]]] = sidx[start:i] start = i outt[c1D[sidx[start]]] = sidx[start:] return outtdef numba2(cubes): c1D = np.ravel_multi_index(cubes.T, cubes.max(0)+1) sidx = c1D.argsort() out = _numba2(sidx, c1D) return out
cubes.npz数据计时-
In [4]: cubes = np.load('cubes.npz')['array']In [5]: %timeit numpy1(cubes) ...: %timeit numba1(cubes) ...: %timeit numba2(cubes)2.38 s ± 14.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)2.13 s ± 25.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)1.8 s ± 5.95 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
选择#1: 我们可以通过
numexpr大型数组来实现进一步的加速
c1D,例如-
import numexpr as nes0,s1 = cubes[:,0].max()+1,cubes[:,1].max()+1d = {'s0':s0,'s1':s1,'c0':cubes[:,0],'c1':cubes[:,1],'c2':cubes[:,2]}c1D = ne.evaluate('c0+c1*s0+c2*s0*s1',d)
这将适用于所有需要的地方
c1D。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)