【问题标题】:numpy.tile did not work as Matlab repmatnumpy.tile 不能作为 Matlab repmat
【发布时间】:2015-08-26 23:19:44
【问题描述】:

根据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 中相同的数组,那么等价的是什么?

编辑 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]]]  

【问题讨论】:

  • numpy.dstack((b,b,b,b,b)) 以正确的形状给出奇怪的输出。
  • @farenorth 给了你正确的东西。你有没有在 0:4 看到 b_[:,:,i] for i?不要将显示样式与实际值混淆。
  • MATLAB 改变第一个维度最快,最后一个最慢。因此它将“平面”显示为 (:,:,1) 等。numpy 以最快的速度迭代最后一个维度,最后一个维度。因此它将“平面”显示为 2d 块,在本例中为 3x5。

标签: python matlab numpy equivalent


【解决方案1】:

NumPy 函数通常不是 matlab 函数的“直接”替代品。通常,“等效”函数的使用方式存在细微差别。适应确实需要时间,但我发现过渡非常值得。

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

numpy.tile(A, reps)

通过将 A 重复 reps 给出的次数来构造一个数组。

如果 reps 的长度为 d,则结果的维度为 max(d, A.ndim)。

如果 A.ndim

在这种情况下,您的数组被转换为[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)

在这种情况下,我使用元组乘法来“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]]

祝你好运!

【讨论】:

  • 嗨@farenorth,这会产生不同的输出,类似于 numpy.dstack(),来自 Matlab 版本。
  • 非常感谢。你的回答非常清楚和完整。对不起,我对 Python-numpy 数组缺乏了解。
  • 没问题!我记得当我从 Matlab 切换到这里时,both 让我感到困惑。
【解决方案2】:

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

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 等价物 - 或多或少:

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])

困惑了吗?

【讨论】:

  • 感谢您的澄清。
猜你喜欢
  • 2015-04-27
  • 1970-01-01
  • 1970-01-01
  • 2014-09-15
  • 1970-01-01
  • 2018-03-14
  • 1970-01-01
  • 2010-12-15
  • 1970-01-01
相关资源
最近更新 更多