首页 文章

numpy.tile没有像Matlab repmat那样工作

提问于
浏览
1

根据What is the equivalent of MATLAB's repmat in NumPy,我尝试使用python从3x3数组构建3x3x5数组 .

在Matlab中,这项工作正如我所料 .

a = [1,1,1;1,2,1;1,1,1];
a_= repmat(a,[1,1,5]);

大小(a_)= 3 3 5

但对于numpy.tile

b = numpy.array([[1,1,1],[1,2,1],[1,1,1]])
b_ = numpy.tile(b, [1,1,5])

b_.shape =(1,3,15)

如果我想生成与Matlab相同的数组,那么它的等价物是什么?

Edit 1

我期望获得的输出是

b_(:,:,1) =

1 1 1  
1 2 1  
1 1 1  

b_(:,:,2) =

1 1 1  
1 2 1  
1 1 1  

b_(:,:,3) =

1 1 1  
1 2 1  
1 1 1  

b_(:,:,4) =  

1 1 1  
1 2 1  
1 1 1  
b_(:,:,5) =

1 1 1  
1 2 1  
1 1 1

但@farenorth和 numpy.dstack 给出的是什么

[[[1 1 1 1 1]  
[1 1 1 1 1]  
[1 1 1 1 1]]  

[[1 1 1 1 1]  
[2 2 2 2 2]  
[1 1 1 1 1]]  

[[1 1 1 1 1]  
[1 1 1 1 1]  
[1 1 1 1 1]]]

2 回答

  • 10

    NumPy函数通常不是matlab函数的“插入式”替换 . 通常情况下,“等效”函数的使用方式存在细微差别 . 它需要时间来适应,但我发现过渡非常值得 .

    在这种情况下, np.tile 文档指出当您尝试将数组平铺到比定义的更高维度时会发生什么,

    numpy.tile(A,reps)通过重复A由reps给出的次数构造一个数组 . 如果reps的长度为d,则结果的维度为max(d,A.ndim) . 如果A.ndim <d,则通过预先添加新轴将A提升为d维 . 因此,形状(3)阵列被提升为(1,3)用于2-D复制,或形状(1,1,3)用于3-D复制 . 如果这不是所需的行为,请在调用此函数之前手动将A提升为d维 .

    在这种情况下,您的数组将被转换为 [1, 3, 3] 的形状,然后进行平铺 . 因此,为了获得您想要的行为,请确保将新的单例维度附加到您想要的数组中,

    >>> b_ = numpy.tile(b[..., None], [1, 1, 5])
    >>> print(b_.shape)
    (3, 3, 5)
    

    请注意,我使用了 None (即 np.newaxis )和省略号表示法来指定数组末尾的新维度 . 您可以找到有关这些功能的更多信息here .

    受OP评论启发的另一个选择是:

    b_ = np.dstack((b, ) * 5)
    

    在这种情况下,我've used tuple multiplication to ' repmat'数组,然后由np.dstack构造 .

    正如@hpaulj指出的那样,Matlab和NumPy以不同的方式显示矩阵 . 要复制Matlab输出,您可以执行以下操作:

    >>> for idx in xrange(b_.shape[2]):
    ...    print 'b_[:, :, {}] = \n{}\n'.format(idx, str(b_[:, :, idx]))
    ...
    b_[:, :, 0] = 
    [[1 1 1]
     [1 2 1]
     [1 1 1]]
    
    b_[:, :, 1] = 
    [[1 1 1]
     [1 2 1]
     [1 1 1]]
    
    b_[:, :, 2] = 
    [[1 1 1]
     [1 2 1]
     [1 1 1]]
    
    b_[:, :, 3] = 
    [[1 1 1]
     [1 2 1]
     [1 1 1]]
    
    b_[:, :, 4] = 
    [[1 1 1]
     [1 2 1]
     [1 1 1]]
    

    祝好运!

  • 3

    让我们尝试比较,注意使形状和 Value 多样化 .

    octave:7> a=reshape(0:11,3,4)
    a =
        0    3    6    9
        1    4    7   10
        2    5    8   11
    
    octave:8> repmat(a,[1,1,2])
    ans =
    ans(:,:,1) =
        0    3    6    9
        1    4    7   10
        2    5    8   11
    ans(:,:,2) =    
        0    3    6    9
        1    4    7   10
        2    5    8   11
    

    numpy equivalent - 或多或少:

    In [61]: a=np.arange(12).reshape(3,4)    
    In [62]: np.tile(a,[2,1,1])
    Out[62]: 
    array([[[ 0,  1,  2,  3],
            [ 4,  5,  6,  7],
            [ 8,  9, 10, 11]],
    
           [[ 0,  1,  2,  3],
            [ 4,  5,  6,  7],
            [ 8,  9, 10, 11]]])
    

    numpy再次,但与 order F 更好地匹配MATLAB Fortran派生的布局

    In [63]: a=np.arange(12).reshape(3,4,order='F')    
    In [64]: np.tile(a,[2,1,1])
    Out[64]: 
    array([[[ 0,  3,  6,  9],
            [ 1,  4,  7, 10],
            [ 2,  5,  8, 11]],
    
           [[ 0,  3,  6,  9],
            [ 1,  4,  7, 10],
            [ 2,  5,  8, 11]]])
    

    我在一开始就添加了新的numpy维度,因为在很多方面它更好地复制了最后添加它的MATLAB实践 .

    尝试在最后添加新维度 . 形状是(3,4,5),但你可能不喜欢显示器 .

    np.tile(a[:,:,None],[1,1,2])
    

    另一个考虑因素 - 当你压扁瓷砖时会发生什么?

    octave:10> repmat(a,[1,1,2])(:).'
    ans =    
        0    1    2    3    4    5    6    7    8    9   10   11 
    0    1    2    3     4    5    6    7    8    9   10   11
    

    订单F a

    In [78]: np.tile(a[:,:,None],[1,1,2]).flatten()
    Out[78]: 
    array([ 0,  0,  3,  3,  6,  6,  9,  9,  1,  1,  4,  4,  7,  7, 10, 10,  2,
            2,  5,  5,  8,  8, 11, 11])
    
    In [79]: np.tile(a,[2,1,1]).flatten()
    Out[79]: 
    array([ 0,  3,  6,  9,  1,  4,  7, 10,  2,  5,  8, 11,  0,  3,  6,  9,  1,
            4,  7, 10,  2,  5,  8, 11])
    

    使用C顺序数组:

    In [80]: a=np.arange(12).reshape(3,4)
    
    In [81]: np.tile(a,[2,1,1]).flatten()
    Out[81]: 
    array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,  0,  1,  2,  3,  4,
            5,  6,  7,  8,  9, 10, 11])
    

    最后一个匹配Octave布局 .

    那样做:

    In [83]: a=np.arange(12).reshape(3,4,order='F')
    
    In [84]: np.tile(a[:,:,None],[1,1,2]).flatten(order='F')
    Out[84]: 
    array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,  0,  1,  2,  3,  4,
            5,  6,  7,  8,  9, 10, 11])
    

    困惑了吗?

相关问题