# what is the fastest way to insert elements diagonally in 2d numpy array?

• Last Update :
• Techknowledgy :

Create a new bigger matrix, that have space left for the zeros. Copy the original matrix to a submatrix, clip and reshape:

```matrix = numpy.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
])

matrix_new = numpy.zeros((4, 5))
matrix_new[: -1, 1: ] = matrix.reshape(3, 4)
matrix_new = matrix_new.reshape(-1)[: -4].reshape(4, 4)```

or in a more generalized form:

```matrix = numpy.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
])

d = matrix.shape[0]
assert matrix.shape[1] == d - 1
matrix_new = numpy.ndarray((d, d + 1), dtype = matrix.dtype)
matrix_new[: , 0] = 0
matrix_new[: -1, 1: ] = matrix.reshape((d - 1, d))
matrix_new = matrix_new.reshape(-1)[: -d].reshape(d, d)```

Here's one way (but I can't promise that it is the fastest way):

```In[62]: a
Out[62]:
array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
])

In[63]: b = np.zeros((a.shape[0], a.shape[1] + 1), dtype = a.dtype)

In[64]: i = np.arange(b.shape[0])

In[65]: j = np.arange(b.shape[1])

In[66]: b[np.not_equal.outer(i, j)] = a.ravel() # or a.flat,
if a is C - contiguous

In[67]: b
Out[67]:
array([
[0, 1, 2, 3],
[4, 0, 5, 6],
[7, 8, 0, 9],
[10, 11, 12, 0]
])```

It works for any 2-d array `a`:

```In[72]: a
Out[72]:
array([
[17, 18, 15, 19, 12],
[16, 14, 11, 16, 17],
[19, 11, 16, 11, 14]
])

In[73]: b = np.zeros((a.shape[0], a.shape[1] + 1), dtype = a.dtype)

In[74]: i = np.arange(b.shape[0])

In[75]: j = np.arange(b.shape[1])

In[76]: b[np.not_equal.outer(i, j)] = a.flat

In[77]: b
Out[77]:
array([
[0, 17, 18, 15, 19, 12],
[16, 0, 14, 11, 16, 17],
[19, 11, 0, 16, 11, 14]
])```

another approach, probably slower, with append and reshape

```import numpy as np

mat = np.array(range(1, 13)).reshape(4, 3)
mat

array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
])

z = np.zeros((3, 1), dtype = mat.dtype)
m3 = np.append(z, mat.reshape(3, 4), 1)
np.append(m3, 0).reshape(4, 4)

array([
[0, 1, 2, 3],
[4, 0, 5, 6],
[7, 8, 0, 9],
[10, 11, 12, 0]
])```

Looks like you are taking the lower and upper triangular arrays and separating them with a diagonal of zeros. This sequence does that:

`In[54]: A = np.arange(1, 13).reshape(4, 3)`

Target array, with one more column

`In[55]: B = np.zeros((A.shape[0], A.shape[1] + 1), dtype = A.dtype)`

Copy over the lower tri (without the diagonal)

`In[56]: B[: ,: -1] += np.tril(A, -1)`

Lets say you have a p x q numpy 2d array A, here is a sample with (p,q) as (3,4):

```In[]: A = np.arange(1, 13).reshape(4, 3)
In[]: A
Out[]:
array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
])```

Before this we create a 2d array with column index values of non-diagonal elements for the new 2d array like this

`In[]: columnIndexArray = np.delete(np.meshgrid(np.arange(q + 1), np.arange(p))[0], np.arange(0, p * (q + 1), q + 2)).reshape(p, q)`

The output of the above will look as follows:

```In[]: columnIndexArray
Out[]:
array([
[1, 2, 3],
[0, 2, 3],
[0, 1, 3],
[0, 1, 2]
])```

Now assign the non diagonal elements with the values from A

```In[]: B[np.arange(p)[: , None], columnIndexArray] = A

In[]: B
Out[]:
array([
[0., 1., 2., 3.],
[4., 0., 5., 6.],
[7., 8., 0., 9.],
[10., 11., 12., 0.]
])```

Again, I don't know how fast it is but you could try using `numpy.lib.stride_tricks.as_strided`:

```import numpy as np
as_strided = np.lib.stride_tricks.as_strided

matrix = (np.arange(12) + 1).reshape((4, 3))

n, m = matrix.shape
t = matrix.reshape((m, n))
t = np.hstack((np.array([
[0] * m
]).T, t))
t = np.vstack((t, [0] * (n + 1)))
q = as_strided(t, (n, n), (t.itemsize * n, 8))
print(q)```

Output:

```[
[0 1 2 3]
[4 0 5 6]
[7 8 0 9]
[10 11 12 0]
]```

Suggestion : 2

If you depend on the current behavior, then we suggest copying the returned array explicitly, i.e., use np.diagonal(a).copy() instead of just np.diagonal(a). This will work with both past and future versions of NumPy.,In versions of NumPy prior to 1.7, this function always returned a new, independent array containing a copy of the values in the diagonal.,In NumPy 1.7 and 1.8, it continues to return a copy of the diagonal, but depending on this fact is deprecated. Writing to the resulting array continues to work as it used to, but a FutureWarning is issued.,The sub-arrays whose main diagonals we just obtained; note that each corresponds to fixing the right-most (column) axis, and that the diagonals are “packed” in rows.

```>>> a = np.arange(4).reshape(2, 2) >>>
a
array([
[0, 1],
[2, 3]
]) >>>
a.diagonal()
array([0, 3]) >>>
a.diagonal(1)
array([1])```
```>>> a = np.arange(8).reshape(2, 2, 2);
a
array([
[
[0, 1],
[2, 3]
],
[
[4, 5],
[6, 7]
]
]) >>>
a.diagonal(0, # Main diagonals of two arrays created by skipping
...0, # across the outer(left) - most axis last and
...1) # the "middle"(row) axis first.
array([
[0, 6],
[1, 7]
])```
```>>> a[: ,: , 0] # main diagonal is[0 6]
array([
[0, 2],
[4, 6]
]) >>>
a[: ,: , 1] # main diagonal is[1 7]
array([
[1, 3],
[5, 7]
])```
```>>> a = np.arange(9).reshape(3, 3) >>>
a
array([
[0, 1, 2],
[3, 4, 5],
[6, 7, 8]
]) >>>
np.fliplr(a).diagonal() # Horizontal flip
array([2, 4, 6]) >>>
np.flipud(a).diagonal() # Vertical flip
array([6, 4, 2])```

Suggestion : 3

Last Updated : 02 Sep, 2020

Output:

```Original 3 d array: [
[
[0 1 2 3]
[4 5 6 7]
[8 9 10 11]
[12 13 14 15]
]

[
[16 17 18 19]
[20 21 22 23]
[24 25 26 27]
[28 29 30 31]
]

[
[32 33 34 35]
[36 37 38 39]
[40 41 42 43]
[44 45 46 47]
]
]
2 d diagonal array: [
[0 5 10 15]
[16 21 26 31]
[32 37 42 47]
]```

Suggestion : 4

To create a two-dimensional array with the flattened input as a diagonal, use the numpy.diagflat() method −,Create a two-dimensional array with the flattened input as an upper diagonal in Numpy,Create a two-dimensional array with the flattened input as lower diagonal in Numpy,Create an array with ones at and below the given diagonal and zeros elsewhere with a different output type in Numpy

At first, import the required library −

`import numpy as np`

Create a 2D array using the numpy.array() method −

```arr = np.array([
[5, 10],
[15, 20]
])```

Displaying our array −

`print("Array...\n", arr)`

Get the dimensions of the Array −

`print("\nArray Dimensions...\n", arr.ndim)`

Get the shape of the Array −

`print("\nOur Array Shape...\n", arr.shape)`

Suggestion : 5

With higher dimensional arrays, you have many more options. In a two-dimensional array, the elements at each index are no longer scalars but rather one-dimensional arrays:,The easiest way to create an array is to use the array function. This accepts any sequence-like object (including other arrays) and produces a new NumPy array containing the passed data. For example, a list is a good candidate for conversion:,Another way is to use the np.ix_ function, which converts two 1D integer arrays to an indexer that selects the square region:,One of the key features of NumPy is its N-dimensional array object, or ndarray, which is a fast, flexible container for large data sets in Python. Arrays enable you to perform mathematical operations on whole blocks of data using similar syntax to the equivalent operations between scalar elements:

```In[13]: data1 = [6, 7.5, 8, 0, 1]

In[14]: arr1 = np.array(data1)

In[15]: arr1
Out[15]: array([6., 7.5, 8., 0., 1.])```
```In[27]: arr1 = np.array([1, 2, 3], dtype = np.float64)

In[28]: arr2 = np.array([1, 2, 3], dtype = np.int32)

In[29]: arr1.dtype In[30]: arr2.dtype
Out[29]: dtype('float64') Out[30]: dtype('int32')```
```In[45]: arr = np.array([
[1., 2., 3.],
[4., 5., 6.]
])

In[46]: arr
Out[46]:
array([
[1., 2., 3.],
[4., 5., 6.]
])

In[47]: arr * arr In[48]: arr - arr
Out[47]: Out[48]:
array([
[1., 4., 9.], array([
[0., 0., 0.],
[16., 25., 36.]
])[0., 0., 0.]
])```
```In[51]: arr = np.arange(10)

In[52]: arr
Out[52]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In[53]: arr[5]
Out[53]: 5

In[54]: arr[5: 8]
Out[54]: array([5, 6, 7])

In[55]: arr[5: 8] = 12

In[56]: arr
Out[56]: array([0, 1, 2, 3, 4, 12, 12, 12, 8, 9])```
```In[75]: arr[1: 6]
Out[75]: array([1, 2, 3, 4, 64])```
```In[83]: names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])

In[84]: data = np.random.randn(7, 4)

In[85]: names
Out[85]:
array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'],
dtype = '|S4')

In[86]: data
Out[86]:
array([
[-0.048, 0.5433, -0.2349, 1.2792],
[-0.268, 0.5465, 0.0939, -2.0445],
[-0.047, -2.026, 0.7719, 0.3103],
[2.1452, 0.8799, -0.0523, 0.0672],
[-1.0023, -0.1698, 1.1503, 1.7289],
[0.1913, 0.4544, 0.4519, 0.5535],
[0.5994, 0.8174, -0.9297, -1.2564]
])```

Suggestion : 6

To get the primary diagonal element, we need to find the Mat00, Mat11, Mat22, and Mat33; it is formed by using the same row and column name.,Remember that we always put the row number first and then the column number. The correct format of an element X inside a matrix becomes X (R, C), where R and C represent the row and column where the element is present.,In the above code, we get the rows and col of and matrix and we have used the two for loops. In the inner loop, we checked the conditions if the i and j are equal than print the corresponding element.,In this method, we will use the two for loops for columns and a loop for rows, and in the inner loop, we check for the condition.

```Primary Diagonal: 1, 3, 9, 3
Secondary Diagonal: 4, 2, 8, 6```
```Primary Diagonal: 2, 2, 2
Secondary Diagonal: 2, 2, 2```
```[
['a', 'b', 'c'],
['d', 'e', 'f'],
['g', 'h', 'i']
]```
```[
['a', 'b', 'c'],
['d', 'e', 'f'],
['g', 'h', 'i']
]
[
[27, 34],
[61, 18]
]
[
['one', 'two', 'three'],
['four', 'five', 'six']
]```
`Primary Diagonal is: 1, 3, 9, 3,`
`Secondary Diagonal: 4, 2, 8, 6,`