-3

I want to get diagonals from a matrix in Matlab. For example, given the following matrix

M = [1  1   4   5   4
     2  5   1   2   2
     4  1   2   1   3
     1  3   1   1   1
     1  2   3   3   1]

I want to get a list of vectors which make the upper diagonals: {[1 1 1 1], [4 2 3], [5 2] [4]}.

One attempt

I want to replace if-clauses by a while-loop in Matlab

     if (i==j)
        A(t+1,i) = M(i,j)
     end
     if (i==j+1) 
        A(t+1,i) = M(i,j)
     end
     ...
     if (i==j+N) 
        A(t+1,i) = M(i,j)
     end

To store all diagonals of the matrix

t = 0;
while (t < 5)   % if-clauses replaced here by this
   for i=1:5
      for j=i:5
          if (i == j+t)
             trend(t+1,i) = M(i,j); 
          end
      end
   end
t = t + 1;
end

The idea is to store elements into the matrix trend with the condition i == j+t that is a condition I find holds for the diagonals of the upper triangle. The if-clauses are replaced by false pseudocode, which tries to go through the upper triangle of the matrix, but false because no "1" vector found in trend


How can you get diagonals from a matrix in Matlab?

Léo Léopold Hertz 준영
  • 134,464
  • 179
  • 445
  • 697
  • What is your question again? I'm sorry but despite the length and two blocks of code, I don't understand at all. – Andras Deak -- Слава Україні Mar 31 '16 at 11:48
  • I get the strong feeling you're trying to reinvent the wheel here but I have no idea because it's not clear at all what you're trying to do and your sample does not function. – sco1 Mar 31 '16 at 11:54
  • 1
    too many loops.. For instance, you can create an off-diagonal matrix like this `diag(ones(1,99), 1)`. Also the if-statements if the marked section are overwriting the same location in `A`.. Also what is `t`? – Amro Mar 31 '16 at 11:59
  • 3
    Please make sure the first code is actually correct and running before continuing: http://stackoverflow.com/help/mcve – Amro Mar 31 '16 at 12:05
  • Matlab is short for matrix laboratory. Since matricies are already basic building blocks there are simple methods to read/write them, like mentioned before: diag() reads or writes the diagonal and can even be used on off-diagonal entries. Others are zeros(), ones(), rand(), magic(),.... – mike Mar 31 '16 at 12:18
  • 1
    Adding some sample input and output matrices would make this a lot easier to understand. but make them *5*-by-*5* rather than *100*-by-*100* – Dan Mar 31 '16 at 12:22
  • 1
    "To store all diagonals of the matrix" what does this mean? Are you trying to recreate the `triu` function? As in `triu(M)`? – Dan Mar 31 '16 at 12:24
  • 1
    Since you used random input, you need to include the sample input that matches that output. Better would be to not use a random input but something more predictable like `reshape(1:25,5,5)` – Dan Mar 31 '16 at 12:25
  • 2
    @Masi can you also show the expected output for that sample 5x5 matrix you posted? – Amro Mar 31 '16 at 12:27
  • 1
    I see, this can be easily done with the `spdiags` function – Amro Mar 31 '16 at 12:35
  • 4
    @Masi you could have eliminated a whole lot of confusion from this question if you'd just written `M = [...]` instead of that first nested loop which actually has nothing to do with your question what so ever – Dan Mar 31 '16 at 12:39

3 Answers3

3

If I understood correctly, you want to use the spdiags function to extract the upper off-diagonals. Example:

N = 5;
M = magic(N)
D = spdiags(M, 1:N-1)
DD = arrayfun(@(i) D(i+1:end,i).', 1:N-1, 'Uniform',false)
celldisp(DD)

The result:

M =
    17    24     1     8    15
    23     5     7    14    16
     4     6    13    20    22
    10    12    19    21     3
    11    18    25     2     9

D =
     0     0     0     0
    24     0     0     0
     7     1     0     0
    20    14     8     0
     3    22    16    15

DD = 
    [1x4 double]    [1x3 double]    [1x2 double]    [15]
DD{1} =
    24     7    20     3
DD{2} =
     1    14    22
DD{3} =
     8    16
DD{4} =
    15
Amro
  • 123,847
  • 25
  • 243
  • 454
  • I accept this answer because it generalises the situation well. – Léo Léopold Hertz 준영 Mar 31 '16 at 12:51
  • 1
    Thanks. The issue here was the way you described your problem was very confusing.. In the future, always consider adding a small example of the input and the expected output you're looking for, along with how you tried to solve it. But it's important to include examples... – Amro Mar 31 '16 at 13:03
2

try to replace this part:

         if (i==j)
            A(t+1,i) = M(i,j)
         end
         if (i==j+1) 
            A(t+1,i) = M(i,j)
         end
         ...
         if (i==j+N) 
            A(t+1,i) = M(i,j)
         end

with:

             if (i>=j && i<=j+N) 
                A(t+1,i) = M(i,j)
             end
Léo Léopold Hertz 준영
  • 134,464
  • 179
  • 445
  • 697
Adilli Adil
  • 1,231
  • 1
  • 17
  • 25
1

I don't know why you want a while loop. What about directly indexing each of your diagonals using MATLAB's built-in diag function:

n = size(M,1)
for t = 1:n-1
    trend{t} = M(diag(true(n-t,1),t));    
end
Dan
  • 45,079
  • 17
  • 88
  • 157