# Assigning row of values to a lower triangular matrix

I want to assign a linear row of values to the elements of a lower triangular matrix,

i.e., if the row of values is {1,2,3,4}, then the matrix (4 X 4) should be:

{{1, 0, 0, 0}, {2, 1, 0, 0}, {3, 2, 1, 0}, {4, 3, 2, 1}}


I can do this with a (nested) For loop, but was wondering if there was any easier way.

• How about an arbitrary set of values, say {1.12, 2.45, 3.77, 4.23}. How would I transfer these to a lowertriangular matrix? Mr. Wizard's answer looks pertinent but any other way? Thanks Jul 29, 2013 at 12:52
• Jorge, you shouldn't be so fast to Accept an answer. This question is still young. :-) Jul 29, 2013 at 13:09
• Unfortunately I agree :P Also +1 for waking this site up :P
– Kuba
Jul 29, 2013 at 13:13
• First battery of timings added to my answer. Jul 29, 2013 at 13:25

vals = {1,2,3,4};
n = Length@vals

NestList[PadLeft[#, n+1][[ ;; -2]] &, vals, n-1] // Transpose

{{1, 0, 0, 0}, {2, 1, 0, 0}, {3, 2, 1, 0}, {4, 3, 2, 1}}


30% faster approach:

NestList[ArrayPad[#, {-1, 1}] &, Reverse@vals, n - 1] // Reverse

• It appears we were thinking alike. +1 I'll be interested to see how this one performs. Jul 29, 2013 at 13:07
• @Mr.Wizard Comparison could be interesting :) I like @sebhofer s array because I was approaching to this with MapIndexed, it wasn't pretty.
– Kuba
Jul 29, 2013 at 13:11
• Oh, I think the MapIndexed solution is kind of cute :) Jul 29, 2013 at 13:12
• See my timings; I found one faster but it was inspired by your method. Jul 29, 2013 at 13:44
• I also added a note regarding the mass application of PadRight that I think will interest you. Jul 29, 2013 at 14:17
vals = {1, 2, 3, 4};
Reverse /@
ListConvolve[ConstantArray[1, Length@vals], vals, 1, 0, Times, List]


And a couple of special forces functions:

Reverse@HankelMatrix@Reverse@vals
LowerTriangularize@ToeplitzMatrix@vals


The problem with LowerTriangularize @ ToeplitzMatrix @ vals, altho it is compact, is that one is stuffing a matrix with values that are then set to zero later, which is a waste of effort. It is better to construct the lower triangular Toeplitz matrix outright with specially chosen vectors, like so:

ToeplitzMatrix[#, SparseArray[1 -> First[#], Length[#]]] & @ vals

• Wow! I've never used those (esoteric?) matrix functions before. +1! Jul 29, 2013 at 20:54

I propose these:

vals = {1, 2, 3, 4};

n = 4;

SparseArray[Array[Band[{#, 1}] -> vals[[#]] &, n], n] // Normal

Reverse @ PadRight @ NestList[Rest, Reverse @ vals, n-1]

PadLeft @ NestList[Most, vals, n-1] ~Reverse~ {1, 2}

UpperTriangularize[NestList[RotateRight, vals, n-1]] ~Reverse~ {1, 2}

With[{r = Reverse@vals}, PadLeft[r, n, 0, n - #] & ~Array~ n]

#@Partition[#@vals, n, 1, 1, 0] &[Reverse]

PadRight[#, n] & /@ NestList[Rest, Reverse @ vals, n - 1] // Reverse

Table[
v = Prepend[Most@v, vals[[i]]],
{v, {ConstantArray[0, n]}},
{i, n}
] // First


All produce:

{{1, 0, 0, 0}, {2, 1, 0, 0}, {3, 2, 1, 0}, {4, 3, 2, 1}}


### Notes:

Something I've known for a while but didn't account for here is that PadLeft/PadRight on a ragged array of packed lists unpacks. My second and third methods have this problem. By using PadRight on each packed vector these can be greatly improved for that specific case.

# Timings

Alright, I believe we have enough options for the first timing comparison. Using my flavor of Timo's timeAvg:

SetAttributes[timeAvg, HoldFirst]

timeAvg[func_] := Do[If[# > 0.3, Return[#/5^i]] & @@ Timing@Do[func, {5^i}], {i, 0, 15}]


And this (packed) data:

n = 1500;
vals = RandomInteger[9999, 1500];


The timings for my proposals:

SparseArray[Array[Band[{#, 1}] -> vals[[#]] &, n], n]                   // timeAvg
Reverse@PadRight@NestList[Rest, Reverse @ vals, n - 1]                  // timeAvg
PadLeft@NestList[Most, vals, n - 1] ~Reverse~ {1, 2}                    // timeAvg
UpperTriangularize[NestList[RotateRight, vals, n - 1]] ~Reverse~ {1, 2} // timeAvg
With[{r = Reverse@vals}, PadLeft[r, n, 0, n - #] & ~Array~ n]           // timeAvg
#@Partition[#@vals, n, 1, 1, 0] &[Reverse]                              // timeAvg
PadRight[#, n] & /@ NestList[Rest, Reverse @ vals, n - 1] // Reverse    // timeAvg
Table[
v = Prepend[Most@v, vals[[i]]],
{v, {ConstantArray[0, n]}},
{i, n}
] // First // timeAvg


1.669

0.1342

0.1778

0.0362

0.003744

0.008112

0.004992

0.003992

And other's proposals:

f[i_, j_] /; i < j := 0
f[i_, j_] := vals[[i - j + 1]]
Array[f, {n, n}] // timeAvg

Table[If[i >= j, vals[[i - j + 1]], 0], {i, n}, {j, n}] // timeAvg

NestList[PadLeft[#, n + 1][[ ;; -2]] &, vals, n - 1] // Transpose // timeAvg

NestList[ArrayPad[#, {-1, 1}] &, Reverse@vals, n - 1] // Reverse // timeAvg

Reverse /@ ListConvolve[ConstantArray[1, Length@vals], vals, 1, 0, Times, List] // timeAvg

LowerTriangularize@MapIndexed[RotateRight, ConstantArray[Reverse@vals, n]] // timeAvg

Array[vals[[#1 - #2 + 1]] UnitStep[#1 - #2] &, {n, n}] // timeAvg


1.981

1.576

0.010608

0.006864

0.2246

0.134

3.573

I expected Band to perform better which is why I led with it, but it actually scales very poorly. Kuba's method is faster than any of my four original ones but it inspired my fifth method which is the fastest so far on this test. I'll update timings as more options come in and with more detailed tests.

panda-34 get's his own special section for these beautiful incantations; the fastest yet!

Reverse @ HankelMatrix @ Reverse @ vals      // timeAvg
LowerTriangularize @ ToeplitzMatrix @ vals   // timeAvg


0.002872

0.002496

• I like yours the best btw, especially the NestList ones Jul 29, 2013 at 13:00
• @sebhofer Thank you. Jul 29, 2013 at 13:24
• Could you test my MapIndexed solution? I think it should be reasonably fast... Jul 29, 2013 at 13:37
• @sebhofer Sorry, I missed your adding that. I'll get working on it. Jul 29, 2013 at 13:40
• See if you can beat LowerTriangularize@ToeplitzMatrix@vals (I added it to my answer) Jul 29, 2013 at 17:15

Variation of Nasser's code (which I find a bit cleaner, although it is longer)

f[i_, j_] /; i < j := 0
f[i_, j_] := i - j + 1
Array[f, {4, 4}] // MatrixForm


For arbitrary values one could adapt this and do

vals={1,3,5,7};
f[i_, j_] /; i < j := 0
f[i_, j_] := vals[[i - j + 1]]


And another one, just to be silly (and to not let Mr. Wizard win with all his NestList based solutions ;)

vals={1,3,5,7};
LowerTriangularize@MapIndexed[RotateRight, ConstantArray[Reverse@vals, Length@vals]]

• I really like Array; you could also write Array[If[# >= #2, # - #2 + 1, 0] &, {4, 4}] which is closer to Nasser's. Jul 29, 2013 at 12:48
• @Mr.Wizard I thought about adding your suggestion but Artes has it in his answer, so I guess it's not necessary... Jul 29, 2013 at 12:58

I recommend Array since it is faster than Table and UnitStep (faster than If)

(m = Array[(#1 - #2 + 1) UnitStep[#1 - #2] &, {4, 4}]) // MatrixForm If there is an input vector e.g.

v = {3, 5, 7, 11};


we can reformulate existing approach to this form:

Array[ v[[#1 - #2 + 1]] UnitStep[#1 - #2] &, {4, 4}] // MatrixForm • Perhaps I misunderstand but I assumed that the OP wanted an arbitrary vector for values. Jul 29, 2013 at 12:45
• @Mr.Wizard Now that I reread the question I think you are right Jul 29, 2013 at 12:47
• It should be clear enough to beginners that one can play with pure functions inside Array to define different vectors. Jul 29, 2013 at 12:49
• So give us an example. :-) Jul 29, 2013 at 12:51
• @Mr.Wizard Exempli gratia: Array[(#1^2 - 2 #2 + 3) UnitStep[#1 - #2] &, {4, 4}] Jul 29, 2013 at 12:54

one way

(m = Table[If[i >= j, i - j + 1, 0], {i, 4}, {j, 4}]) // MatrixForm r = {3, 99, 27, 49};
(m = Table[If[i >=  j, r[[i - j + 1]], 0], {i, 4}, {j, 4}]) // MatrixForm • How about an arbitrary set of values, say {1.12, 2.45, 3.77, 4.23}. How would I transfer these to a lowertriangular matrix? Jul 29, 2013 at 12:51

Also:

ClearAll[toLTM]
toLTM[n_Integer] := Composition[Transpose, PadLeft, Range, Reverse, Range]@n
(* or toLTM[n_Integer] := Reverse /@ PadLeft @ Range @ Range @ n *)

toLTM[v_List] := Transpose @
PadLeft @ Extract[v, List /@ Range @ Reverse @ Range @ Length @ v]

toLTM @ 4 // TeXForm


$\left( \begin{array}{cccc} 1 & 0 & 0 & 0 \\ 2 & 1 & 0 & 0 \\ 3 & 2 & 1 & 0 \\ 4 & 3 & 2 & 1 \\ \end{array} \right)$

toLTM @ CharacterRange["a", "d"] // TeXForm


$\left( \begin{array}{cccc} \text{a} & 0 & 0 & 0 \\ \text{b} & \text{a} & 0 & 0 \\ \text{c} & \text{b} & \text{a} & 0 \\ \text{d} & \text{c} & \text{b} & \text{a} \\ \end{array} \right)$

PadRight[Take[RotateRight[Reverse@list, #], #], 4] & /@ Range[Length[list]]


or

    NestList[RotateRight, Reverse@list,
Length@list][[-Length@list ;; -1]] // LowerTriangularize
`