I have the following tiling call in my code.
np.tile(array, (10000, 1))
I call this many times for different arrays, but the shape of those arrays are always the same.
So is there a function that I can define which does this operation faster? For example by pre-generating the shape, and then just filling it up more efficiently with the new array for each call?
CodePudding user response:
You can do the same thing with a 'filling'
For example:
In [92]: arr = np.arange(12).reshape(3,4)
In [93]: np.tile(arr, (5,1))
Out[93]:
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],
[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In [94]: _.shape
Out[94]: (15, 4)
filling will be easiest if we start with a 3d array, and reshape it:
In [96]: res = np.zeros((5,3,4),arr.dtype)
...: res[:] = arr[None,:,:] # or just res[:] = arr
...: res = res.reshape(15,4)
In [97]:
In [97]: res
Out[97]:
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],
[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
Comparative times:
In [98]: timeit np.tile(arr, (5,1))
9.35 µs ± 13.4 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
In [99]: %%timeit
...: res = np.zeros((5,3,4),arr.dtype)
...: res[:] = arr[None,:,:]
...: res = res.reshape(15,4)
3.6 µs ± 154 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
Or do the reshape in the assignment step, since it's a view:
In [107]: %%timeit
...: res = np.zeros((15,4),arr.dtype)
...: res.reshape(5,3,4)[:] = arr
2.91 µs ± 131 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
CodePudding user response:
If your arrays are all the same shape, you could collect them into a higher-dimensional array and tile all of them at once. Here's an example with 10 arrays of shape (3, 3)
:
In [4]: arrs.shape
Out[4]: (10, 3, 3)
In [5]: np.tile(arrs, (1, 10000, 1)).shape
Out[5]: (10, 30000, 3)
Depending on the shape of your arrays, you may need to add more dimensions to the tiling. If you provide a sample array, I can update this answer.