代码之家  ›  专栏  ›  技术社区  ›  Gabriel

按块分割numpy数组

  •  1
  • Gabriel  · 技术社区  · 6 年前

    我要切一个数组( aa )给定三个值( N1, N2, N3 )定义切片条件的,如下所示:

    import numpy as np
    
    N1, N2, N3 = 200, 500000, 30
    aa = np.random.uniform(0., 1., N1*N2)
    
    bb = []
    for i in range(N1):
        bb += list(aa[i * N2:(i * N2) + N3])
    

    此代码生成一个新数组 bb 遵循规则:

    1. 第一次 N3 要素 AA公司
    2. N2 元素并添加以下内容 N3号 要素 AA公司
    3. 重复2直到 AA公司 筋疲力尽

    我能通过NoMPI索引更快地执行这个过程吗?

    3 回复  |  直到 6 年前
        1
  •  3
  •   Divakar    6 年前

    简单地重塑为 2D 将前N3列切片-

    bb = aa.reshape(N1,N2)[:,:N3].ravel()
    

    什么时候? N3 超过 N2

    如果 N3号 超过 氮气 ,那些 aa[i * N2:(i * N2) + N3] 在迭代中会有重叠。为了解决这种情况,我们可以创建滑动窗口,然后对行进行切片,直到有足够的长度,然后对剩余的窗口进行循环。-

    from skimage.util.shape import view_as_windows
    
    starts = np.arange(len(aa), step=N2)
    lens = len(aa) - np.arange(len(aa), step=N2)
    rem_lens = lens[lens < N3]
    m0 = lens < N3
    
    l1 = N3*(~m0).sum()
    l2 = rem_lens.sum() 
    out = np.empty(l1+l2, dtype=aa.dtype)
    out[:l1] = view_as_windows(aa,(N3))[::N2].ravel()
    rem_starts = starts[m0]
    ss = l1+np.r_[0,rem_lens.cumsum()]
    for s,i,j in zip(rem_starts, ss[:-1], ss[1:]):
        out[i:j] = aa[s:]
    
        2
  •  2
  •   Mad Physicist    6 年前

    你可以通过改变数组的形状来做得更优雅首先将初始阵列设为二维:

    N1, N2, N3 = 200, 500000, 30
    aa = np.random.uniform(0., 1., (N1, N2))
    

    现在只需要去掉一大块 N3 沿着第二维度:

    bb = aa[:, :N3]
    

    如果你需要 bb 要平坦,就要:

    bb = aa[:, :N3].ravel()
    
        3
  •  0
  •   abarnert    6 年前

    你可以用纽比的 array_split split 做同样的事情要简单一点。

    不过,这可能不会比 有效率的 是的。

    存储一堆数组切片 aa[i * N2:(i * N2) + N3] 是切片数的线性时间。在NumPy中执行这个循环(因此在C循环中而不是Python循环中,假设您使用的是CPython)会快一点但除非你有大量的切片,否则这可能无关紧要。

    但是,将每个切片转换为一个列表 list(aa[i * N2:(i * N2) + N3]) 然后扩展现有的列表是非常缓慢的。它可能会占用你99%以上的时间,所以优化另外1%是无关紧要的。NumPy无法加速将每个片段转换为列表。

    所以,如果你真的不需要名单,就别打电话了 list 是的。您只需使用数组列表和 chain 根据需要将它们组合在一起,或者您可以构建 a custom-strided array 在数组列表之外,或者您可以 ravel 原始数组变成你想要的形状。

    如果你 需要一个列表,这本来就很慢,你没什么办法。