I have 30x30 matrix and need to extrapolate lower triangle numbers

4 visualizzazioni (ultimi 30 giorni)
I need to pull out everything below the diagonal (the lower triagnle numbers), but I don't want to use tril and change the diagonal and upper triangle to zeros. I just want to pull out the lower triangle numbers so that I can make a vector out of its values.
Anything is helpful!! Thank you!

Risposta accettata

John D'Errico
John D'Errico il 7 Giu 2019
You just want to extract the lower triangle, whatever is in it? The result going into a vector?
A = magic(5) - 10
A =
7 14 -9 -2 5
13 -5 -3 4 6
-6 -4 3 10 12
0 2 9 11 -7
1 8 15 -8 -1
V = A(logical(tril(ones(size(A)))))
V =
7
13
-6
0
1
-5
-4
2
8
3
9
15
11
-8
-1
That includes the diagonal. But if you want the strictly lower triangle, just set a second argument for tril.
  3 Commenti
Jan
Jan il 8 Giu 2019
V = A(tril(true(size(A))))
avoids the creation and conversion of the double matrix.
John D'Errico
John D'Errico il 9 Giu 2019
Yes. I knew I was being sloppy there, but I was too lazy to think of the better alternative suggested by Jan. True works better.

Accedi per commentare.

Più risposte (1)

Jan
Jan il 7 Giu 2019
Modificato: Jan il 8 Giu 2019
x = rand(5, 5);
y = x(tril(true(size(x))))
What is the reason to avoid tril?
Maybe:
s = size(x);
y = x((1:s(1)).' >= (1:s2)) % lower left triangle
n = 1;
y = x((1+n:s(1)+n).' >= (1:s2)) % lower left triangle + n diagonals above
% or below, if n < 0
  2 Commenti
aet
aet il 7 Giu 2019
I'm not super experienced with this stuff so I apologize. I'm fine using tril as long as I can maintain any zeros in the lower triangle when I pull out the values for the lower triangle. This isn't working for my matrix. It is saying that the logical indices contain a true value outside of the array bounds.
Jan
Jan il 8 Giu 2019
Modificato: Jan il 10 Giu 2019
@aet: Then you made a typo in your tests or used my example of "5", although your matrix is smaller. I've replaced the fix size 5 by the real size of the matrix. The 1st example is equivalent to John's suggestion, but
tril(true(size(A)))
creates the triangular index matrix in the logical type directly, while
logical(tril(ones(size(A)))
creates a double matrix at first, which is 8 times larger. For larger arrays, this needs more resources and an additional conversion.
With
n = 1;
y = x((1+n:s(1)+n).' >= (1:s2))
you can exclude e.g. the main diagonal also: n=-1.
Some timings:
x = rand(1000, 1000);
tic
for k = 1:1000
y = x(tril(true(size(x))));
end
toc
tic
for k = 1:1000
y = x(logical(tril(ones(size(x)))));
end
toc
tic
for k = 1:1000
s = size(x);
y = x((1:s(1)).' >= (1:s(2)));
end
toc
tic
for k = 1:1000
s = size(x);
y = x(bsxfun(@ge, (1:s(1)).', 1:s(2)));
end
toc
Elapsed time is 5.526872 seconds.
Elapsed time is 10.652150 seconds.
Elapsed time is 6.415982 seconds. % Auto-expanding
Elapsed time is 6.094049 seconds. % BSXFUN
I'm sureprised that tril(true()) is faster than the bsxfun approach.

Accedi per commentare.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by