FooBar - 4 months ago 51

Python Question

I would like to change diagonal elements from a 2d matrix. These are both main and non-main diagonals.

**numpy.diagonal()**

In NumPy 1.10, it will return a read/write view, Writing to the returned

array will alter your original array.

**numpy.fill_diagonal()**, **numpy.diag_indices()**

Only works with main-diagonal elements

Here is my use case: I want to recreate a matrix of the following form, which is very trivial using diagonal notation given that I have all the *x*, *y*, *z* as arrays.

Answer

You could always use slicing to assign a value or array to the diagonals.

Passing in a list of row indices and a list of column indices lets you access the locations directly (and efficiently). For example:

```
>>> z = np.zeros((5,5))
>>> z[np.arange(5), np.arange(5)] = 1 # diagonal is 1
>>> z[np.arange(4), np.arange(4) + 1] = 2 # first upper diagonal is 2
>>> z[np.arange(4) + 1, np.arange(4)] = [11, 12, 13, 14] # first lower diagonal values
```

changes the array of zeros `z`

to:

```
array([[ 1., 2., 0., 0., 0.],
[ 11., 1., 2., 0., 0.],
[ 0., 12., 1., 2., 0.],
[ 0., 0., 13., 1., 2.],
[ 0., 0., 0., 14., 1.]])
```

In general for a `k x k`

array called `z`

, you can set the `i`

th upper diagonal with

```
z[np.arange(k-i), np.arange(k-i) + i]
```

and the `i`

th lower diagonal with

```
z[np.arange(k-i) + i, np.arange(k-i)]
```

Note: if you want to avoid calling `np.arange`

several times, you can simply write `ix = np.arange(k)`

once and then slice that range as needed:

```
np.arange(k-i) == ix[:-i]
```