I would like to execute the equivalent of the following MATLAB code using NumPy: repmat([1; 1], [1 1 1])
. How would I accomplish this?
This is how I understood it out of a bit of fiddling around. Happy to be corrected and hope this helps.
Say you have a matrix M of 2x3 elements. This has two dimensions, obviously.
I could see no difference between Matlab and Python while asking to manipulate the input matrix along the dimensions the matrix already has. Thus the two commands
repmat(M,m,n) % matlab
np.tile(M,(m,n)) # python
are really equivalent for a matrix of rank 2 (two dimensions).
The matters goes counter-intuitive when you ask for repetition/tiling over more dimensions than the input matrix has. Going back to the matrix M of rank two and shape 2x3, it is sufficient to look at what happens to the size/shape of the output matrix. Say the sequence for manipulation is now 1,1,2.
In Matlab
> size(repmat(M,1,1,2))
ans =
2 3 2
it has copied the first two dimensions (rows and columns) of the input matrix and has repeated that once into a new third dimension (copied twice, that is). True to the naming repmat
for repeat matrix.
In Python
>>> np.tile(M,(1,1,2)).shape
(1, 2, 6)
it has applied a different procedure since, I presume, the sequence (1,1,2) is read differently than in Matlab. The number of copies in the direction of columns, rows and out-of-plane dimension are being read from right to left. The resulting object has a different shape from Matlab. One can no longer assert that repmat
and tile
are equivalent instructions.
In order to get tile
to behave like repmat
, in Python one has to make sure that the input matrix has as many dimensions as the elements are in the sequence. This is done, for example, by a little preconditioning and creating a related object N
N = M[:,:,np.newaxis]
Then, at the input side one has N.shape = (2,3,1)
rather than M.shape = (2,3)
and at the output side
>>> np.tile(N,(1,1,2)).shape
(2, 3, 2)
which was the answer of size(repmat(M,1,1,2))
. I presume this is because we have guided Python to add the third dimension to the right of (2,3) rather than to its left, so that Python works out the sequence (1,1,2) as it was intended in the Matlab way of reading it.
The element in [:,:,0]
in the Python answer for N will contain the same values as the element (:,:,1)
the Matlab answer for M.
Finally, I can't seem to find an equivalent for repmat
when one uses the Kronecker product out of
>>> np.kron(np.ones((1,1,2)),M).shape
(1, 2, 6)
unless I then precondition M into N as above. So I would argue that the most general way to move on is to use the ways of np.newaxis
.
The game gets trickier when we consider a matrix L of rank 3 (three dimensions) and the simple case of no new dimensions being added in the output matrix. These two seemingly equivalent instructions will not produce the same results
repmat(L,p,q,r) % matlab
np.tile(L,(p,q,r)) # python
because the row, column, out-of-plane directions are (p,q,r) in Matlab and (q,r,p) in Python, which was not visible with rank-2 arrays. There, one has to be careful and obtaining the same results with the two languages would require more preconditioning.
I am aware that this reasoning may well not be general, but I could work it out only this far. Hopefully this invites other fellows to put it to a harder test.
See NumPy for Matlab users.
Matlab:
repmat(a, 2, 3)
Numpy:
numpy.kron(numpy.ones((2,3)), a)
Matlib in Numpy (numpy.matlib.repmat()):
numpy.matlib.repmat(a, 2, 3)
Note that some of the reasons you'd need to use MATLAB's repmat are taken care of by NumPy's broadcasting mechanism, which allows you to do various types of math with arrays of similar shape. So if you had, say, a 1600x1400x3 array representing a 3-color image, you could (elementwise) multiply it by [1.0 0.25 0.25]
to reduce the amount of green and blue at each pixel. See the above link for more information.
Know both tile
and repeat
.
x = numpy.arange(5)
print numpy.tile(x, 2)
print x.repeat(2)
numpy.matlib has a repmat function with a similar interface as the matlab function
from numpy.matlib import repmat
repmat( np.array([[1],[1]]) , 1, 1)
Here is a much better (official) NumPy for Matlab Users link - I'm afraid the mathesaurus one is quite out of date.
The numpy equivalent of repmat(a, m, n)
is tile(a, (m, n)).
This works with multiple dimensions and gives a similar result to matlab. (Numpy gives a 3d output array as you would expect - matlab for some reason gives 2d output - but the content is the same).
Matlab:
>> repmat([1;1],[1,1,1])
ans =
1
1
Python:
In [46]: a = np.array([[1],[1]])
In [47]: np.tile(a, [1,1,1])
Out[47]:
array([[[1],
[1]]])