# Extending an existing matrix
{:.no_toc}
## The goal
Questions to [David Rotermund](mailto:davrot@uni-bremen.de)
## [numpy.tile](https://numpy.org/doc/stable/reference/generated/numpy.tile.html)
```python
numpy.tile(A, reps)
```
> Construct an array by repeating A the number of times given by reps.
>
> If reps has length d, the result will have dimension of max(d, A.ndim).
>
> If A.ndim < d, A is promoted to be d-dimensional by prepending new axes. So a shape (3,) array is promoted to (1, 3) for 2-D replication, or shape (1, 1, 3) for 3-D replication. If this is not the desired behavior, promote A to d-dimensions manually before calling this function.
>
> If A.ndim > d, reps is promoted to A.ndim by pre-pending 1’s to it. Thus for an A of shape (2, 3, 4, 5), a reps of (2, 2) is treated as (1, 1, 2, 2).
>
> Note : Although tile may be used for broadcasting, it is strongly recommended to use numpy’s broadcasting operations and functions.
**You might want to first use numpy.newaxis to create the required additional axis and then use tile.**
Adding a new dimension makes a copy:
```python
import numpy as np
a = np.arange(1, 5)
print(a) # -> [1 2 3 4]
print(a.shape) # -> (4,)
b = a[np.newaxis, :]
print(b.shape) # -> (1, 4)
print(np.may_share_memory(a, b)) # -> True (View)
c = np.tile(a, (1, 1))
print(c.shape) # -> (1, 4)
print(np.may_share_memory(a, c)) # -> False (Copy)
```
Examples:
```python
import numpy as np
a = np.arange(1, 5)[np.newaxis, :]
print(a) # -> [[1 2 3 4]]
print(a.shape) # -> (1, 4)
c = np.tile(a, (1, 1))
print(c) # -> [[1 2 3 4]]
print(c.shape) # -> (1, 4)
c = np.tile(a, (4, 1))
print(c)
print(c.shape) # -> (4, 4)
c = np.tile(a, (1, 4))
print(c) # -> [[1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4]]
print(c.shape) # -> (1, 16)
```
Output:
```python
[[1 2 3 4]
[1 2 3 4]
[1 2 3 4]
[1 2 3 4]]
```
Be very careful if you haven’t newaxis-ed...
```python
import numpy as np
a = np.arange(1, 5)
print(a) # -> [1 2 3 4]
print(a.shape) # -> (4,)
c = np.tile(a, (4))
print(c) # -> [1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4]
print(c.shape) # -> (16,)
c = np.tile(a, (1, 4))
print(c) # -> [[1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4]]
print(c.shape) # -> (1, 16)
c = np.tile(a, (4, 1))
print(c)
print(c.shape) # -> (4, 4)
print()
c = np.tile(a, (4, 1, 1))
print(c)
print(c.shape) # -> (4, 1, 4)
print()
c = np.tile(a, (1, 4, 1))
print(c)
print(c.shape) # -> (1, 4, 4)
print()
c = np.tile(a, (1, 1, 4))
print(c) # -> [[[1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4]]]
print(c.shape) # -> (1, 1, 16)
```
Output:
```python
[[1 2 3 4]
[1 2 3 4]
[1 2 3 4]
[1 2 3 4]]
[[[1 2 3 4]]
[[1 2 3 4]]
[[1 2 3 4]]
[[1 2 3 4]]]
[[[1 2 3 4]
[1 2 3 4]
[1 2 3 4]
[1 2 3 4]]]
```
## [numpy.repeat](https://numpy.org/doc/stable/reference/generated/numpy.repeat.html#numpy-repeat)
**Don’t confuse tile() with repeat()!**
```python
numpy.repeat(a, repeats, axis=None)[source]
```
> Repeat each element of an array after themselves
```python
import numpy as np
a = np.arange(1, 5)
print(a) # -> [1 2 3 4]
print(a.shape) # -> (4,)
b = np.repeat(a, (4))
print(b) # -> [1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4]
print(b.shape) # -> (16,)
```
## [numpy.pad](https://numpy.org/doc/stable/reference/generated/numpy.pad.html)
```python
numpy.pad(array, pad_width, mode='constant', **kwargs)
```
> Pad an array.
> **pad_width** : {sequence, array_like, int}
>
> Number of values padded to the edges of each axis. ((before_1, after_1), ... (before_N, after_N)) unique pad widths for each axis. (before, after) or ((before, after),) yields same before and after pad for each axis. (pad,) or int is a shortcut for before = after = pad width for all axes.
> **constant_values** : sequence or scalar, optional
>
> Used in ‘constant’. The values to set the padded values for each axis.
>
> ((before_1, after_1), ... (before_N, after_N)) unique pad constants for each axis.
>
> (before, after) or ((before, after),) yields same before and after constants for each axis.
>
> (constant,) or constant is a shortcut for before = after = constant for all axes.
>
> Default is 0.
```python
import numpy as np
a = np.arange(1, 5)
print(a) # -> [1 2 3 4]
print(a.shape) # -> (4,)
print(np.pad(a, 2)) # -> [0 0 1 2 3 4 0 0]
print(np.pad(a, [2, 3])) # -> [0 0 1 2 3 4 0 0 0]
print(np.pad(a, [2, 3], constant_values=-1)) # -> [-1 -1 1 2 3 4 -1 -1 -1]
```
```python
import numpy as np
a = np.arange(1, 5).reshape((1, 4))
print(a) # -> [[1 2 3 4]]
print(a.shape) # -> (1, 4)
print(np.pad(a, [[2, 3], [1, 1]]))
```
Output:
```python
[[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 1 2 3 4 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]]
```
### Pad can do more complex padding patterns than just pad with constant values!
> **mode** : str or function, optional
>
> One of the following string values or a user supplied function.
|||
|---|---|
|‘constant’ (default)|Pads with a constant value.|
|‘edge’|Pads with the edge values of array.|
|‘linear_ramp’|Pads with the linear ramp between end_value and the array edge value.|
|‘maximum’|Pads with the maximum value of all or part of the vector along each axis.|
|‘mean’|Pads with the mean value of all or part of the vector along each axis.|
|‘median’|Pads with the median value of all or part of the vector along each axis.|
|‘minimum’|Pads with the minimum value of all or part of the vector along each axis.|
|‘reflect’|Pads with the reflection of the vector mirrored on the first and last values of the vector along each axis.|
|‘symmetric’|Pads with the reflection of the vector mirrored along the edge of the array.|
|‘wrap’|Pads with the wrap of the vector along the axis. The first values are used to pad the end and the end values are used to pad the beginning.|
|‘empty’|Pads with undefined values.|
||Padding function, see Notes.|