16 views (last 30 days)

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!

John D'Errico
on 7 Jun 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.

Jan
on 8 Jun 2019

V = A(tril(true(size(A))))

avoids the creation and conversion of the double matrix.

John D'Errico
on 9 Jun 2019

Sign in to comment.

Jan
on 7 Jun 2019

Edited: Jan
on 8 Jun 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

Jan
on 8 Jun 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.

Sign in to comment.

Sign in to answer this question.

Opportunities for recent engineering grads.

Apply Today
## 1 Comment

## Direct link to this comment

https://nl.mathworks.com/matlabcentral/answers/466034-i-have-30x30-matrix-and-need-to-extrapolate-lower-triangle-numbers#comment_712695

⋮## Direct link to this comment

https://nl.mathworks.com/matlabcentral/answers/466034-i-have-30x30-matrix-and-need-to-extrapolate-lower-triangle-numbers#comment_712695

Sign in to comment.