numpy.tile 没有作为 Matlab repmat 工作
numpy.tile did not work as Matlab repmat
根据 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 函数通常不会'drop-in' 替代 matlab 函数。通常,'equivalent' 函数的使用方式存在细微差别。适应确实需要时间,但我发现这种转变非常值得。
在这种情况下,np.tile
文档指出当您尝试将数组平铺到比定义的更高维度时会发生什么,
numpy.tile(A, reps)
Construct an array by repeating A the number of times given by reps.
If reps has length d, the result will have dimension of max(d, A.ndim).
If A.ndim < d, A is promoted to be d-dimensional by prepending new axes. So a shape (3,) array is promoted to (1, 3) for 2-D replication, or shape (1, 1, 3) for 3-D replication. If this is not the desired behavior, promote A to d-dimensions manually before calling this function.
在这种情况下,您的数组被转换为 [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]]
祝你好运!
让我们尝试比较,注意使形状和值多样化。
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
顺序Fa
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])
迷茫了吗?
根据 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 函数通常不会'drop-in' 替代 matlab 函数。通常,'equivalent' 函数的使用方式存在细微差别。适应确实需要时间,但我发现这种转变非常值得。
在这种情况下,np.tile
文档指出当您尝试将数组平铺到比定义的更高维度时会发生什么,
numpy.tile(A, reps)
Construct an array by repeating A the number of times given by reps.
If reps has length d, the result will have dimension of max(d, A.ndim).
If A.ndim < d, A is promoted to be d-dimensional by prepending new axes. So a shape (3,) array is promoted to (1, 3) for 2-D replication, or shape (1, 1, 3) for 3-D replication. If this is not the desired behavior, promote A to d-dimensions manually before calling this function.
在这种情况下,您的数组被转换为 [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]]
祝你好运!
让我们尝试比较,注意使形状和值多样化。
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
顺序Fa
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])
迷茫了吗?