【问题标题】:Numpy repeat for 2d array二维数组的 Numpy 重复
【发布时间】:2017-02-25 04:52:31
【问题描述】:

给定两个数组,比如说

arr = array([10, 24, 24, 24,  1, 21,  1, 21,  0,  0], dtype=int32)
rep = array([3, 2, 2, 0, 0, 0, 0, 0, 0, 0], dtype=int32)

np.repeat(arr, rep) 返回

array([10, 10, 10, 24, 24, 24, 24], dtype=int32)

有没有办法为一组二维数组复制此功能?

这是给定的

arr = array([[10, 24, 24, 24,  1, 21,  1, 21,  0,  0],
            [10, 24, 24,  1, 21,  1, 21, 32,  0,  0]], dtype=int32)
rep = array([[3, 2, 2, 0, 0, 0, 0, 0, 0, 0],
            [2, 2, 2, 0, 0, 0, 0, 0, 0, 0]], dtype=int32)

是否可以创建一个矢量化的函数?

PS:每行的重复次数不必相同。我正在填充每个结果行以确保它们的大小相同。

def repeat2d(arr, rep):
    # Find the max length of repetitions in all the rows. 
    max_len = rep.sum(axis=-1).max()  
    # Create a common array to hold all results. Since each repeated array will have 
    # different sizes, some of them are padded with zero.
    ret_val = np.empty((arr.shape[0], maxlen))  
    for i in range(arr.shape[0]):
        # Repeated array will not have same num of cols as ret_val.
        temp = np.repeat(arr[i], rep[i])
        ret_val[i,:temp.size] = temp
    return ret_val 

我确实知道 np.vectorize,而且我知道它不会比普通版本带来任何性能优势。

【问题讨论】:

    标签: python arrays numpy vectorization


    【解决方案1】:

    所以你对每一行都有不同的重复数组?但是每行的总重复次数是一样的吗?

    只需对展平的数组执行repeat,然后重新调整为正确的行数。

    In [529]: np.repeat(arr,rep.flat)
    Out[529]: array([10, 10, 10, 24, 24, 24, 24, 10, 10, 24, 24, 24, 24,  1])
    In [530]: np.repeat(arr,rep.flat).reshape(2,-1)
    Out[530]: 
    array([[10, 10, 10, 24, 24, 24, 24],
           [10, 10, 24, 24, 24, 24,  1]])
    

    如果每行的重复次数不同,我们就会遇到填充可变长度行的问题。这出现在其他 SO 问题中。我不记得所有细节,但我认为解决方案是这样的:

    更改rep,使数字不同:

    In [547]: rep
    Out[547]: 
    array([[3, 2, 2, 0, 0, 0, 0, 0, 0, 0],
           [2, 2, 2, 1, 0, 2, 0, 0, 0, 0]])
    In [548]: lens=rep.sum(axis=1)
    In [549]: lens
    Out[549]: array([7, 9])
    In [550]: m=np.max(lens)
    In [551]: m
    Out[551]: 9
    

    创建目标:

    In [552]: res = np.zeros((arr.shape[0],m),arr.dtype)
    

    创建一个索引数组 - 细节需要制定:

    In [553]: idx=np.r_[0:7,m:m+9]
    In [554]: idx
    Out[554]: array([ 0,  1,  2,  3,  4,  5,  6,  9, 10, 11, 12, 13, 14, 15, 16, 17])
    

    平面索引赋值:

    In [555]: res.flat[idx]=np.repeat(arr,rep.flat)
    In [556]: res
    Out[556]: 
    array([[10, 10, 10, 24, 24, 24, 24,  0,  0],
           [10, 10, 24, 24, 24, 24,  1,  1,  1]])
    

    【讨论】:

    • 每行的重复总数不必相同。这就是为什么我要找出 maxlen 然后将每一行填充为相同的大小。
    • 你正在用随机的empty 值填充?我见过可以处理可变长度行的屏蔽插入,但不记得细节了。
    • 是的。我用随机的空值填充它们。虽然我猜在我的情况下用零填充更有意义。
    • 我建议修改您的示例,以便此填充变得重要。
    【解决方案2】:

    另一个类似@hpaulj的解决方案:

    def repeat2dvect(arr, rep):
        lens = rep.sum(axis=-1)
        maxlen = lens.max()
        ret_val = np.zeros((arr.shape[0], maxlen))
        mask = (lens[:,None]>np.arange(maxlen))
        ret_val[mask] = np.repeat(arr.ravel(), rep.ravel())
        return ret_val
    

    我没有存储索引,而是创建了一个布尔掩码并使用掩码来设置值。

    【讨论】:

      猜你喜欢
      • 2016-01-28
      • 1970-01-01
      • 1970-01-01
      • 2021-03-15
      • 2016-09-12
      • 2013-02-01
      • 1970-01-01
      • 2019-02-10
      • 1970-01-01
      相关资源
      最近更新 更多