[Numpy-discussion] "upsample" or scale an array
Robin Kraft
rkraft4 at gmail.com
Sat Dec 3 13:06:22 EST 2011
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/numpy-discussion/attachments/20111203/0dc9ce04/attachment.html>
More information about the NumPy-Discussion
mailing list