Ha! I knew it had to be possible! Thanks Derek. So for and N = 2 (now on my
laptop):
In [70]: M = 1200
In [69]: N = 2
In [71]: a = np.random.randint(0, 255, (M**2)).reshape(M,-1)
In [76]: timeit np.rollaxis(np.tile(a, N**2).reshape(M,N,-1), 2,
1).reshape(M*N,-1)
10 loops, best of 3: 99.1 ms per loop
In [78]: timeit a.repeat(2, axis=0).repeat(2, axis=1)
10 loops, best of 3: 85.6 ms per loop
In [79]: timeit np.kron(a, np.ones((2,2), 'uint8'))
1 loops, best of 3: 521 ms per loop
It turns out np.kron and repeat are pretty straightforward for
multi-dimensional data too - scaling or stretching a stacked array representing
pixel data over time, for example. Nothing changes for np.kron - it handles the
additional dimensionality by itself. With repeat you just tell it to operate on
the last two dimensions.
So to sum up:
1) np.kron is cool for the simplicity of the code and simple scaling to N
dimensions. It's also handy if you want to scale the array elements themselves
too.
2) repeat() along the last N axes is a bit more intuitive (i.e. less magical)
to me and has a better performance profile.
3) Derek's reshape/rolling solution is almost as fast but it gives me a
headache trying to visualize what it's actually doing. I don't want to think
about adding another dimension ...
Thanks for the help folks. Here's scaling of a hypothetical time series (i.e. 3
axes), where each sub-array represents a month.
In [26]: print a
[[[1 2]
[3 4]]
[[1 2]
[3 4]]
[[1 2]
[3 4]]]
In [27]: np.kron(a, np.ones((2,2), dtype='uint8'))
Out[27]:
array([[[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]],
[[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]],
[[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]]])
In [64]: a.repeat(2, axis=1).repeat(2, axis=2)
Out[64]:
array([[[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]],
[[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]],
[[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]]])
On Dec. 3, 2011, at 12:50PM, Derek Homeier wrote:
> On 03.12.2011, at 6:22PM, Robin Kraft wrote:
>
> > That does repeat the elements, but doesn't get them into the desired order.
> >
> > In [4]: print a
> > [[1 2]
> > [3 4]]
> >
> > In [7]: np.tile(a, 4)
> > Out[7]:
> > array([[1, 2, 1, 2, 1, 2, 1, 2],
> > [3, 4, 3, 4, 3, 4, 3, 4]])
> >
> > In [8]: np.tile(a, 4).reshape(4,4)
> > Out[8]:
> > array([[1, 2, 1, 2],
> > [1, 2, 1, 2],
> > [3, 4, 3, 4],
> > [3, 4, 3, 4]])
> >
> > It's close, but I want to repeat the elements along the two axes,
> > effectively stretching it by the lower right corner:
> >
> > array([[1, 1, 2, 2],
> > [1, 1, 2, 2],
> > [3, 3, 4, 4],
> > [3, 3, 4, 4]])
> >
> > It would take some more reshaping/axis rolling to get there, but it seems
> > doable.
> >
> > Anyone know what combination of manipulations would work with the result of
> > np.tile?
> >
> Rolling was the keyword:
>
> np.rollaxis(np.tile(a, 4).reshape(2,2,-1), 2, 1).reshape(4,4))
> [[1 1 2 2]
> [1 1 2 2]
> [3 3 4 4]
> [3 3 4 4]]
>
> I leave the generalisation and timing up to you, but it seems for
> a = np.arange(M**2).reshape(M,-1)
>
> np.rollaxis(np.tile(a, N**2).reshape(M,N,-1), 2, 1).reshape(M*N,-1)
>
> should do the trick.
>
> Cheers,
> Derek
_______________________________________________
NumPy-Discussion mailing list
[email protected]
http://mail.scipy.org/mailman/listinfo/numpy-discussion