np.repeat duplicates each element of a NumPy array in place, which is not the same as repeating the array:
np.repeat([1, 2, 3], 2) # [1 1 2 2 3 3] each element twice
np.tile([1, 2, 3], 2) # [1 2 3 1 2 3] the whole array twice
That difference is the thing to get straight first. After it, the argument that catches people is axis, which flattens your array when you leave it out.
All output below is from real runs on Python 3.12.5, NumPy 2.5.3.
Using np.repeat on a 1D array
The second argument is how many copies of each element you want:
import numpy as np
a = np.array([1, 2, 3])
print("original :", a)
print("np.repeat(a,2):", np.repeat(a, 2), " each element, twice, in place")
print("np.tile(a, 2) :", np.tile(a, 2), " the whole array, twice")
print()
# repeats can differ per element
print("np.repeat(a, [3, 1, 2]):", np.repeat(a, [3, 1, 2]))
print(" three 1s, one 2, two 3s")
Output:
original : [1 2 3]
np.repeat(a,2): [1 1 2 2 3 3] each element, twice, in place
np.tile(a, 2) : [1 2 3 1 2 3] the whole array, twice
np.repeat(a, [3, 1, 2]): [1 1 1 2 3 3]
three 1s, one 2, two 3s
repeat interleaves. tile concatenates.repeats can also be a list with one number per element. That’s how you expand counts into individual records, and a count of zero removes the element.
The result is always a new array. np.repeat never modifies the input.
Why does np.repeat flatten my 2D array?
This is the surprise. Leave axis out on a 2D array and you get a flat 1D result:
import numpy as np
m = np.array([[1, 2],
[3, 4]])
print("original:")
print(m)
print("\nno axis (the DEFAULT) flattens first:")
print(np.repeat(m, 2), " shape", np.repeat(m, 2).shape)
print("\naxis=0 repeats rows:")
print(np.repeat(m, 2, axis=0))
print("\naxis=1 repeats columns:")
print(np.repeat(m, 2, axis=1))
Output:
original:
[[1 2]
[3 4]]
no axis (the DEFAULT) flattens first:
[1 1 2 2 3 3 4 4] shape (8,)
axis=0 repeats rows:
[[1 2]
[1 2]
[3 4]
[3 4]]
axis=1 repeats columns:
[[1 1 2 2]
[3 3 4 4]]
np.repeat(m, 2) returns shape (8,), not a 2×2 grid.| Call | On a 2×2 array | Result shape |
|---|---|---|
np.repeat(m, 2) | Flattens first | (8,) |
np.repeat(m, 2, axis=0) | Each row twice | (4, 2) |
np.repeat(m, 2, axis=1) | Each column twice | (2, 4) |
Always pass axis when the input has more than one dimension. The default is None, and None means flatten. The same axis thinking applies across NumPy arrays of any shape.
Repeat a row or a column n times
These are two different jobs, and they use different functions:
import numpy as np
row = np.array([1, 2, 3])
# repeat a ROW n times: stack copies of it
print("row repeated 3 times:")
print(np.tile(row, (3, 1)))
print()
# a column, widened
col = np.array([[1], [2], [3]])
print("column repeated 4 times:")
print(np.repeat(col, 4, axis=1))
print()
# and the zero-copy version, when you only need to read it
view = np.broadcast_to(row, (3, 3))
print("broadcast_to shape:", view.shape)
print("is it a view?", view.base is not None, " (no memory copied)")
Output:
row repeated 3 times:
[[1 2 3]
[1 2 3]
[1 2 3]]
column repeated 4 times:
[[1 1 1 1]
[2 2 2 2]
[3 3 3 3]]
broadcast_to shape: (3, 3)
is it a view? True (no memory copied)
tile stacks whole rows. repeat widens a column.- Repeat a row n times —
np.tile(row, (n, 1)). - Repeat a column n times —
np.repeat(col, n, axis=1). - Repeat each element n times —
np.repeat(a, n). - Repeat the whole array n times —
np.tile(a, n).
np.broadcast_to is worth knowing for the read-only case. It produces the same shape without copying any data, so it costs almost nothing in memory.
The catch is that a broadcast result is not writable. If you need to modify it, call .copy() and pay for the memory.
np.repeat vs np.tile
Side by side, the distinction stops being confusing:
import numpy as np
a = np.array([1, 2, 3])
print(f"{'call':<26} {'result'}")
print(f"{'np.repeat(a, 2)':<26} {np.repeat(a, 2)}")
print(f"{'np.tile(a, 2)':<26} {np.tile(a, 2)}")
m = np.array([[1, 2], [3, 4]])
print()
print("on a 2D array, tile takes a shape:")
print(np.tile(m, (2, 3)))
print("shape:", np.tile(m, (2, 3)).shape, " 2 blocks down, 3 across")
Output:
call result
np.repeat(a, 2) [1 1 2 2 3 3]
np.tile(a, 2) [1 2 3 1 2 3]
on a 2D array, tile takes a shape:
[[1 2 1 2 1 2]
[3 4 3 4 3 4]
[1 2 1 2 1 2]
[3 4 3 4 3 4]]
shape: (4, 6) 2 blocks down, 3 across
np.repeat | np.tile | |
|---|---|---|
| Pattern | 1 1 2 2 3 3 | 1 2 3 1 2 3 |
| Works on | Elements | The whole array |
| Second argument | A count, or one per element | A count, or a shape tuple |
| Default on 2D | Flattens | Keeps the shape |
| Use for | Expanding counts, upscaling | Stacking copies, building grids |
tile takes a tuple on a 2D array, so np.tile(m, (2, 3)) gives two blocks down and three across.
What np.repeat is actually used for
Two jobs come up constantly:
import numpy as np
# expanding counts into individual records
values = np.array(["a", "b", "c"])
counts = np.array([2, 0, 3])
print("values:", values, "counts:", counts)
print("expanded:", np.repeat(values, counts), " a count of 0 drops it entirely")
print()
# upscaling a small image or grid by an integer factor
grid = np.array([[1, 2],
[3, 4]])
bigger = np.repeat(np.repeat(grid, 3, axis=0), 3, axis=1)
print("3x upscaled grid shape:", bigger.shape)
print(bigger)
Output:
values: ['a' 'b' 'c'] counts: [2 0 3]
expanded: ['a' 'a' 'c' 'c' 'c'] a count of 0 drops it entirely
3x upscaled grid shape: (6, 6)
[[1 1 1 2 2 2]
[1 1 1 2 2 2]
[1 1 1 2 2 2]
[3 3 3 4 4 4]
[3 3 3 4 4 4]
[3 3 3 4 4 4]]
Expanding counts into records is the first. If you have three categories with counts of 2, 0 and 3, np.repeat builds the full list and silently drops the zero.
Upscaling a grid is the second. Repeating along both axes enlarges an image or a heatmap by an integer factor, with hard edges rather than interpolation.
That nearest-neighbour effect is exactly what you want for pixel art or a low-resolution mask, and exactly what you do not want for a photograph.
np.repeat and np.tile performance
Both produce the same number of elements, and one is consistently cheaper:
import numpy as np
import timeit
a = np.arange(1000)
rep = timeit.timeit(lambda: np.repeat(a, 10), number=20_000)
til = timeit.timeit(lambda: np.tile(a, 10), number=20_000)
print(f"np.repeat(a, 10) {rep * 1000:>7.0f} ms")
print(f"np.tile(a, 10) {til * 1000:>7.0f} ms")
print(f"\nboth produce {np.repeat(a, 10).size:,} elements")
print("tile copies whole blocks, repeat interleaves, so tile is the cheaper memory pattern")
Output:
np.repeat(a, 10) 588 ms
np.tile(a, 10) 72 ms
both produce 10,000 elements
tile copies whole blocks, repeat interleaves, so tile is the cheaper memory pattern
tile copies contiguous blocks, which the CPU handles well. repeat interleaves, writing each source element to scattered destinations.
It rarely matters at small sizes. If you’re repeating a large array inside a loop, it’s worth checking whether tile or a broadcast would do the job instead.
Common np.repeat mistakes
| Symptom | Cause | Fix |
|---|---|---|
| Result is 1D | axis left out | Pass axis=0 or axis=1 |
Got 1 2 3 1 2 3 | Wanted repeat, used tile | Swap the function |
Got 1 1 2 2 3 3 | Wanted tile, used repeat | Swap the function |
ValueError on repeats | List length does not match | One count per element |
| Cannot assign to the result | It came from broadcast_to | Call .copy() |
If you are reshaping and rearranging arrays, these cover the neighbouring ground:
- NumPy 3D arrays and axes
- NumPy sum and the axis argument
- NumPy linspace
- NumPy empty arrays
- Find unique values in a NumPy array
- Transpose an array in Python
Frequently asked questions
What does np.repeat do?
It repeats each element of an array in place, so np.repeat([1, 2, 3], 2) gives [1 1 2 2 3 3]. The signature is in the numpy.repeat reference.
What is the difference between np.repeat and np.tile?
repeat duplicates each element in place. tile duplicates the whole array end to end.
Why does np.repeat flatten my 2D array?
Because axis defaults to None, which flattens before repeating. Pass axis=0 or axis=1.
How do I repeat a row n times in NumPy?
np.tile(row, (n, 1)) stacks n copies of the row.
How do I repeat a column n times?
np.repeat(col, n, axis=1), where col has shape (rows, 1).
Can I repeat each element a different number of times?
Yes. Pass a list of counts: np.repeat([1, 2, 3], [3, 1, 2]). A count of 0 removes that element.
Is there a way to repeat without using memory?
np.broadcast_to returns a read-only view of the repeated shape without copying the data.
Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn