# How to select all elements above the main diagonal of matrix?

How to select all elements above the main diagonal of matrix? I need to create a list of them.

The Diagonal command has a second argument that allows listing the elements of the jth superdiagonal. So we can map over all the superdiagonals:

n = 4;
mat = Array[a, {n, n}];
Flatten[Diagonal[mat, #] & /@ Range[n-1]]


which gives a list of all the elements above the diagonal:

{a[1, 2], a[2, 3], a[3, 4], a[1, 3], a[2, 4], a[1, 4]}

• Niiiiice, I learned something new – Rojo Jan 30 '14 at 1:49

Let's use Span with Part:

mat=RandomInteger[{0, 100}, {5, 5}];

Flatten[mat[[#, # + 1 ;;]] & /@ Range]

• Nice, clean, clever, and faster than the naive solution. +1 – ciao Jan 30 '14 at 5:32

I believe that kale's approach is the best, but it can be improved with Join which is considerably faster than Flatten on packed lists, and it is a bit cleaner when written with Array:

Join @@ Array[mat[[#, # + 1 ;;]] &, n - 1]


To make this into a fast function it seems that one needs a Hold attribute (pass-by-reference):

SetAttributes[aboveDiag, HoldFirst];
aboveDiag[a_] := Join @@ Array[a[[#, # + 1 ;;]] &, Length[a] - 1]


Compare timings (done in v7) with bill s's code and R.M's upperElements function. (I left MatrixQ out of upperElements in these tests to eliminate overhead and level the field.)

n = 5000;
mat = RandomInteger[999, {n, n}];

Flatten[Diagonal[mat, #] & /@ Range[n - 1]] // Timing // First

upperElements[mat]                          // Timing // First

aboveDiag[mat]                              // Timing // First

0.3276

0.1872

0.02308


Not quite as superior on non-packed data, but still a good bit faster than the others.

n = 2000;
mat = DeveloperFromPackedArray @ RandomInteger[999, {n, n}];

Flatten[Diagonal[mat, #] & /@ Range[n - 1]] // Timing // First

upperElements[mat]                          // Timing // First

aboveDiag[mat]                              // Timing // First

0.1404

0.0998

0.02308


Inspired by rasher's use of MapIndexed, here is another one that tests the fastest on unpacked data on my system (using last mat above):

Join @@ MapIndexed[Drop[#, #2[]] &, mat] // Timing // First

0.01996


It is much slower than aboveDiag on packed data.

• Join is not only faster but better than flatten (with no second arg) if the matrix can have list elements – Rojo Jan 30 '14 at 6:47
• @Rojo Good point. – Mr.Wizard Jan 30 '14 at 7:05
• Nice tuning, as usual! For non-huge arrays, I use (filter matching this particular problem in this case): FilterRules[ArrayRules[yourArrayHere], {a_, b_} /; b > a] Just seems... neat, if not a hot-rod. – ciao Jan 30 '14 at 7:53
• @rasher You should post that ArrayRules method; it does have flair. – Mr.Wizard Jan 30 '14 at 7:54
• I don't know but I've ran this and upperElemets and aboveDiag have comparable timings for PackedArray. Also in packed case my Pick is two times faster, unless I'm doing something wrong. – Kuba Jan 30 '14 at 8:35

Update:

StatisticsLibraryUpperTriangularMatrixToVector is faster than all posted methods on packed data. Using the set up from @Mr.Wizard's answer:

n = 4000;
mat = RandomInteger[999, {n, n}];

(res0 = StatisticsLibraryUpperTriangularMatrixToVector@mat) //   Timing // First


0.027995

(res1 = Join @@ MapIndexed[Drop[#, #2[]] &, mat] )// Timing // First


0.158976

(res2 = aboveDiag[mat] )// Timing // First


0.250961

res0 == res1 == res2


True

On unpacked data, it is slower than Join@@MapIndexed[...] but faster than aboveDiag:

n = 2000;
mat = DeveloperFromPackedArray @ RandomInteger[999, {n, n}];

(res0 = StatisticsLibraryUpperTriangularMatrixToVector@mat) // Timing // First


0.096986

(res1 = Join @@ MapIndexed[Drop[#, #2[]] &, mat] ) // Timing // First


0.029996

(res2 = aboveDiag[mat] ) // Timing // First


0.384942

res0 == res1 == res2


True

Previous version:

n = 4; mat = Array[a, {n, n}];

StatisticsLibraryUpperTriangularMatrixToVector @ mat


{a[1, 2], a[1, 3], a[1, 4], a[2, 3], a[2, 4], a[3, 4]}

Also

mat[[##]] & @@@ Subsets[Range[n], {2}]
Extract[mat, Subsets[Range[n], {2}]]


{a[1, 2], a[1, 3], a[1, 4], a[2, 3], a[2, 4], a[3, 4]}

n = 4;
mat = Array[a, {n, n}];

Flatten@Table[If[j > i, mat[[i, j]], {}], {i, n}, {j, n}] • I liked the replacing by {} for future flattening. +1 – Rojo Jan 30 '14 at 2:09

Here's an option for square matrices using undocumented properties of SparseArray, which clocks in slightly faster for me than Mr.Wizard's solution:

upperElements[mat_?MatrixQ] := With[{n = Length@mat},
SparseArray[UpperTriangularize[mat, 1]]["NonzeroValues"] ~PadRight~ (n (n - 1)/2)];


This constructs a sparse strictly upper triangular matrix, extracts the non-zero values and then pads it to a length of $n(n-1)/2$, where $n$ is the dimension of the matrix (to account for any upper element that might have been zero).

For non-square matrices of dimension $m\times n$, you might try using a closed form expression for the number of upper triangular entries (see here, for instance).

• How come I didn't think of padright and worried about deleting extra zeros. +1 – Rojo Jan 30 '14 at 7:01
• On my system (v7) this is about six to seven times slower than aboveDiag with n = 5000; mat = RandomInteger[999, {n, n}]; (and leaving out MatrixQ for a fair test). What data are you testing with, and what timings do you get for my data in v9? – Mr.Wizard Jan 30 '14 at 7:04
• @Mr.Wizard I don't have the timings right now, but it was very close to yours, but a wee bit faster. I see from the comments under yours that Kuba got similar results. I don't have v7 installed, so I can't confirm your findings. – rm -rf Jan 30 '14 at 16:55

n = 4;
m = Array[a, {n, n}];
Join @@ Table[m[[ i, j]], {i, n}, {j, i + 1, n}]

{a[1, 2], a[1, 3], a[1, 4], a[2, 3], a[2, 4], a[3, 4]}


just another way:

Join @@ Pick[
m,
UpperTriangularize[ConstantArray[1, {n, n}], 1],
1]