edgarmtze
edgarmtze

Reputation: 25048

Make a general import of upper triangular matrix in MATLAB

I have been trying to make a general import of Ghaul's answer to my earlier question about importing an upper triangular matrix.

Initial Data:

1.0    3.32   -7.23
1.00    0.60
1.00

A = importdata('A.txt')

A =

    1.0000    3.3200   -7.2300
    1.0000    0.6000       NaN
    1.0000       NaN       NaN

So you will have to shift the two last rows, like this:

A(2,:) = circshift(A(2,:),[0 1])
A(3,:) = circshift(A(3,:),[0 2])

A =

    1.0000    3.3200   -7.2300
    NaN       1.0000    0.6000
    NaN       NaN       1.0000

and then replace the NaNs with their symmetric counterparts:

A(isnan(A)) = A(isnan(A)')

A =

    1.0000    3.3200   -7.2300
    3.3200    1.0000    0.6000
   -7.2300    0.6000    1.0000

I have this, so we get the complete matrix for any size:

A = importdata('A.txt')
for i =  (1:size(A)-1)
    A(i+1,:) = circshift(A(i+1,:),[0 i]);
end 
A(isnan(A)) = A(isnan(A)');

Is this approach the best? There must be something better. I remember someone told me to try not to use for loops in MATLAB.

UPDATE
So this is the result. Is there any way to make it faster without the loop?

A = importdata('A.txt')
for i =  (1:size(A)-1)
    A(i+1,:) = circshift(A(i+1,:),[0 i])
end
A(isnan(A)) = 0;
A = A + triu(A, 1)';

Upvotes: 2

Views: 1092

Answers (2)

gnovice
gnovice

Reputation: 125854

Here's another general solution that should work for any size upper triangular matrix. It uses the functions ROT90, SPDIAGS, and TRIU:

>> A = [1 3.32 -7.23; 1 0.6 nan; 1 nan nan];  %# Sample matrix
>> A = spdiags(rot90(A),1-size(A,2):0);       %# Shift the rows
>> A = A+triu(A,1).'                         %'# Mirror around the main diagonal

A =

    1.0000    3.3200   -7.2300
    3.3200    1.0000    0.6000
   -7.2300    0.6000    1.0000

Upvotes: 3

Jonas
Jonas

Reputation: 74940

Here's one way without loop. If you have a more recent version of Matlab, you may want to check which solution is really faster, since loops aren't as bad as they used to be.

A = A'; %'# transpose so that linear indices get the right order
out = tril(ones(size(A))); %# create an array of indices
out(out>0) = A(~isnan(A)); %# overwrite the indices with the right number
out = out + triu(out',1); %'# fix the upper half of the array

Upvotes: 2

Related Questions