0

I have a numpy array like:

np.array([1,2,3,4])

and I want to convert it to a lower triangular matrix like

np.array([
    [4, 0, 0, 0],
    [3, 4, 0, 0],
    [2, 3, 4, 0],
    [1, 2, 3, 4]
])

, without for loop.... how can i do it?

MoRe
  • 2,296
  • 2
  • 3
  • 23
  • 1
    Does this answer your question? [Convert 1d array to lower triangular matrix](https://stackoverflow.com/questions/51439271/convert-1d-array-to-lower-triangular-matrix) – medium-dimensional Jun 08 '22 at 18:53
  • 1
    `scipy.linalg.toeplitz(a[::-1], np.zeros_like(a))`, if `scipy` can be used. – Michael Szczesny Jun 08 '22 at 18:56
  • 1
    @medium-dimensional no, it isn't my answer, i tried it and couldn't get what I want – MoRe Jun 08 '22 at 19:01
  • @MichaelSzczesny Thanks, it was highly helpful, but I prefer to just use numpy. if I can't, it is ok... thanks again – MoRe Jun 08 '22 at 19:03
  • 1
    Don't reinvent the wheel. `b = np.arange(len(a)); np.tril(a[::-1][b[:,None] - b])` – Michael Szczesny Jun 08 '22 at 19:16
  • @MichaelSzczesny thanks, it was perfect.. wish you answered it, so I can accept it... – MoRe Jun 08 '22 at 19:40
  • 1
    `scipy.linalg.toeplitz` is ~2x faster and [implemented](https://github.com/scipy/scipy/blob/v1.8.1/scipy/linalg/_special_matrices.py#L139-L199) in 4 lines of `numpy`. Admittedly, with a pointer that moves backwards from the middle of the array towards the start without checking bounds. You don't see that very often in python. – Michael Szczesny Jun 08 '22 at 20:17

1 Answers1

4

A similar solution to proposed in a comment by Michael Szczesny can be:

b = np.arange(a.size)
result = np.tril(np.take(a, b - b[:,None] + a.size - 1, mode='clip'))

The result is:

array([[4, 0, 0, 0],
       [3, 4, 0, 0],
       [2, 3, 4, 0],
       [1, 2, 3, 4]])
Valdi_Bo
  • 30,023
  • 4
  • 23
  • 41