By my tests, np.repeat is a little faster than np.tile:
X = np.repeat(arr[None,:], 3, axis=0)
Alternatively, use np.concatenate:
X = np.concatenate([[arr]] * 3, axis=0)
arr = np.arange(10000 * 1000).reshape(10000, 1000)
%timeit np.repeat(arr[None,:], 3, axis=0)
%timeit np.tile(arr, (3, 1, 1))
%timeit np.concatenate([[arr]] * 3, axis=0)
# Read-only, array cannot be modified.
%timeit np.broadcast_to(arr, (3, *arr.shape))
# Creating copy of the above.
%timeit np.broadcast_to(arr, (3, *arr.shape)).copy()
170 ms ± 3.82 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
187 ms ± 3.12 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
243 ms ± 3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
10.9 µs ± 218 ns per loop (mean ± std. dev. of 7 runs, 100000 loops
189 ms ± 2.45 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)each)
np.array_equals(np.repeat(arr[None,:], 3, axis=0),
np.tile(arr, (3, 1, 1))
True
Answer from coldspeed95 on Stack OverflowBy my tests, np.repeat is a little faster than np.tile:
X = np.repeat(arr[None,:], 3, axis=0)
Alternatively, use np.concatenate:
X = np.concatenate([[arr]] * 3, axis=0)
arr = np.arange(10000 * 1000).reshape(10000, 1000)
%timeit np.repeat(arr[None,:], 3, axis=0)
%timeit np.tile(arr, (3, 1, 1))
%timeit np.concatenate([[arr]] * 3, axis=0)
# Read-only, array cannot be modified.
%timeit np.broadcast_to(arr, (3, *arr.shape))
# Creating copy of the above.
%timeit np.broadcast_to(arr, (3, *arr.shape)).copy()
170 ms ± 3.82 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
187 ms ± 3.12 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
243 ms ± 3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
10.9 µs ± 218 ns per loop (mean ± std. dev. of 7 runs, 100000 loops
189 ms ± 2.45 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)each)
np.array_equals(np.repeat(arr[None,:], 3, axis=0),
np.tile(arr, (3, 1, 1))
True
Sounds like a job for np.tile:
In [101]: np.tile(A, (3,1,1))
Out[101]:
array([[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]],
[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]],
[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]])
The second argument specifies the number of copies on each dimension.
There are a number of options in numpy:
The simplest is
np.stack, with the new axis set to 0:result = np.stack((arr,) * m, axis=0)This is a generalization of
np.vstack, which can accept a variablemin the same way:result = np.vstack((arr,) * m)Since you are looking to expand the first dimension and not the second, you can use
np.tile:result = np.tile(arr, [m, 1])For this simple case, you can repeat the elements individually for the same result using
np.repeat. This is a bit hacky, but it works just as well:result = np.repeat([arr], m, axis=0)If
arris already a numpy array, you can add the leading dimension more explicitly:result = np.repeat(arr[None, :], m, axis=0)A slightly more convoluted method, but which showcases what is going on under the hood better is using
np.concatenate:np.concatenate(([arr],) * m, axis=0)In the same spirit as
concatenate, you can use the constructornp.arraydirectly:np.array([arr] * m)An ugly method is to use muliplication (combined with broadcasting):
result = arr * np.ones((m, 1), dtype=np.int8)Setting the dtype to a very small integer type pretty much ensures that the result will be promoted to the actual type of your array.
The previous methods copy the array multiple times to get the 2D data. But since the data is repeated, you don't actually need to copy it. Instead, you can make a view that creates a fake first dimension using broadcasting. Specifically, the
np.broadcast_tofunction will do exactly what you want:result = np.broadcast_to(arr, [m, len(arr)])There is a more general approach even than the previous to making views is
np.lib.stride_tricks.as_strided.First, let's reiterate the warning from the documentation:
Warning
This function has to be used with extreme care, see notes.
Unless you know the byte-size of the dtype you plan on using ahead of time, it's a good idea to ensure that
arris a numpy array to get the strides from it:arr = np.asanyarray(arr) result = np.lib.stride_tricks.as_strided(arr, shape=(m, arr.size), strides=(0,) + arr.strides)
In the last two cases, if you want to expand the view into a full buffer that contains a proper copy for each element, you can copy the data:
result = result.copy()
If you don't do the expansion, you will effectively be simulating the behavior of multiple references to the same list, where modifying any element changes all elements in the same column.
You can use:
import numpy as np
arr, m = [1,2,3,4], 3
np.vstack([arr]*m)
Output:
array([[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 2, 3, 4]])
On another note, why do you need to create such a matrix? You may be looking for numpy broadcasting without the need of repeating your array.
One can use np.repeat methods together with np.newaxis:
import numpy as np
test = np.random.randn(40,40,3)
result = np.repeat(test[np.newaxis,...], 10, axis=0)
print(result.shape)
>> (10, 40, 40, 3)
Assuming you're looking to copy the values 10 times, you can just stack 10 of the array:
def repeat(arr, count):
return np.stack([arr for _ in range(count)], axis=0)
axis=0 is actually the default, so it's not really necessary here, but I think it makes it clearer that you're adding the new axis on the front.
In fact, this is pretty much identical to what the examples for stack are doing:
>>> arrays = [np.random.randn(3, 4) for _ in range(10)]
>>> np.stack(arrays, axis=0).shape
(10, 3, 4)
At first glance you might think repeat or tile would be a better fit.
But repeat is about repeating over an existing axis (or flattening the array), so you'd need to reshape either before or after. (Which is just as efficient, but I think not as simple.)
And tile (assuming you use an array-like reps—with scalar reps it basically repeat) is about filling out a multidimensional spec in all directions, which is much more complex than what you want for this simple case.
All of these options will be equally efficient. They all copy the data 10 times over, which is the expensive part; the cost of any internal processing, building tiny intermediate objects, etc. is irrelevant. The only way to make it faster is to avoid copying. Which you probably don't want to do.
But if you do… To share row storage across the 10 copies, you probably want broadcast_to:
def repeat(arr, count):
return np.broadcast_to(arr, (count,)+arr.shape)
Notice that broadcast_to doesn't actually guarantee that it avoids copying, just that it returns some kind of readonly view where "more than one element of a broadcasted array may refer to a single memory location". In practice, it's going to avoid copying. If you actually need that to be guaranteed for some reason (or if you want a writable view—which is usually going to be a terrible idea, but maybe you have a good reason…), you have to drop down to as_strided:
def repeat(arr, count):
shape = (count,) + arr.shape
strides = (0,) + arr.strides
return np.lib.stride_tricks.as_strided(
arr, shape=shape, strides=strides, writeable=False)
Notice that half the docs for as_strided are warning that you probably shouldn't use it, and the other half are warning that you definitely shouldn't use it for writable views, so… make sure this is what you want before doing it.
numpy.tile
np.tile(my_input_array, 3)
Output
array([-1.02295637, -0.60583836, -0.42240581, -0.78376377, -0.85821456,
-1.02295637, -0.60583836, -0.42240581, -0.78376377, -0.85821456,
-1.02295637, -0.60583836, -0.42240581, -0.78376377, -0.85821456])
Edit: just noticed @hpaulj's answer. I'll still leave my answer but he mentioned np.tile first.
Just use tile method which multiplies the array with given shape and reshape method to structure it. Use x.shape[0]*x.shape[1] to change it into a column vector without explicitly giving the shape dimensions!
x=np.tile(x,(3,1))
y=x.reshape(x.shape[0]*x.shape[1])
This should clarify:
import numpy as np
lst = [1, 2, 3, 4]
four_list = 4 * lst
print(four_list)
np_arr = np.array(lst)
np_multiplied_arr = 4 * np_arr
print(np_multiplied_arr)
np_four_arr = np.tile(np_arr, 4)
print(np_four_arr)
Result:
[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
[ 4 8 12 16]
[1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4]
Note how the code that works to repeat (or tile) a list in Python doesn't work as expected in Numpy, but there is the .tile() operation to help out.
It may not be the best solution but you can do this:
import numpy as np
# Our list
my_list = [1, 2, 3]
# How many times we want to repeat the list
times_to_repeat = 3
# Our final numpy array
my_numpy_array = np.array(my_list*times_to_repeat)
Thats what we will get:
array([1, 2, 3, 1, 2, 3, 1, 2, 3])
But if your input is in numpy array you can do it like that:
import numpy as np
# Our list
my_list = list(np.array([1, 2, 3]))
# How many times we want to repeat the list
times_to_repeat = 3
# Our final numpy array
my_numpy_array = np.array(my_list*times_to_repeat)
The output will be the same as above, its a simple workaround
In [1]: data = np.arange(-50,50,10)
To repeat each element 5 times use np.repeat:
In [3]: np.repeat(data, 5)
Out[3]:
array([-50, -50, -50, -50, -50, -40, -40, -40, -40, -40, -30, -30, -30,
-30, -30, -20, -20, -20, -20, -20, -10, -10, -10, -10, -10, 0,
0, 0, 0, 0, 10, 10, 10, 10, 10, 20, 20, 20, 20,
20, 30, 30, 30, 30, 30, 40, 40, 40, 40, 40])
To repeat the array 5 times use np.tile:
In [2]: np.tile(data, 5)
Out[2]:
array([-50, -40, -30, -20, -10, 0, 10, 20, 30, 40, -50, -40, -30,
-20, -10, 0, 10, 20, 30, 40, -50, -40, -30, -20, -10, 0,
10, 20, 30, 40, -50, -40, -30, -20, -10, 0, 10, 20, 30,
40, -50, -40, -30, -20, -10, 0, 10, 20, 30, 40])
Note, however, that sometimes you can take advantage of NumPy broadcasting instead of creating a larger array with repeated elements.
For example, if
z = np.array([1, 2])
v = np.array([[3], [4], [5]])
then to add these arrays to produce
[[4 5]
[5 6]
[6 7]]
you do not need to use tile:
In [12]: np.tile(z, (3,1))
Out[12]:
array([[1, 2],
[1, 2],
[1, 2]])
In [13]: np.tile(v, (1,2))
Out[13]:
array([[3, 3],
[4, 4],
[5, 5]])
In [14]: np.tile(z, (3,1)) + np.tile(v, (1,2))
Out[14]:
array([[4, 5],
[5, 6],
[6, 7]])
Instead, NumPy will broadcast the arrays for you:
In [15]: z + v
Out[15]:
array([[4, 5],
[5, 6],
[6, 7]])
Simply use np.repeat:
In [5]: data.repeat(5)
Out[5]:
array([-50, -50, -50, -50, -50, -40, -40, -40, -40, -40, -30, -30, -30,
-30, -30, -20, -20, -20, -20, -20, -10, -10, -10, -10, -10, 0,
0, 0, 0, 0, 10, 10, 10, 10, 10, 20, 20, 20, 20,
20, 30, 30, 30, 30, 30, 40, 40, 40, 40, 40])