Matlab:How to find the indices of rows without any zero in a matrix? - matlab

How to find the indices of rows without any zero in a matrix?
Example:
A = [
14 0 6 9 8 17
85 14 1 3 0 99
0 0 0 0 0 0
29 4 5 8 7 46
0 0 0 0 0 0
17 0 5 0 0 49
]
the desired result :
V =[4]

Since Adiel did not post an answer, I'll make their comment a CW: the command
V = find(all(A,2))
does the job, because all(A,2) processes every row, returning 1 if there are any nonzero entries. Then find returns the indices of nonzero entries, which are the desired row numbers.
Similarly, V = find(all(A,1)) works column-wise.

Related

Why are the eigenvalues of eig() sorted in ascending order?

I'm trying to find eigenvalues of a matrix with eig.
I define the matrix with example data:
A = magic(5)
A =
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
and
D = eig(A,'matrix')
D =
65.0000 0 0 0 0
0 -21.2768 0 0 0
0 0 -13.1263 0 0
0 0 0 21.2768 0
0 0 0 0 13.1263
But if I use
C = cov(A)
and get eigenvalues from the covariance matrix, this is the result:
DC = eig(C,'matrix')
DC =
-0.0000 0 0 0 0
0 35.4072 0 0 0
0 0 44.9139 0 0
0 0 0 117.5861 0
0 0 0 0 127.0928
Why are the eigenvalues from the covariance matrix sorted in ascending order?
Sorting is merely a choice of convenience. There's no such thing as a 'real' position of an eigenvector, just as (x,y) is just as valid as (y,x). Since a lot of matrix techniques work on eigenvectors in order of decreasing eigenvalue (i.e. most important first), it makes sense to structure them accordingly.

Create a matrix from a vector such that its height and width are powers of multiples in matlab

I have tried multiple solutions in matlab to convert a vector for example
A = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
into
B= [ 1 2 3 4 ]
5 6 7 8
9 10 11 12
13 14 15 16
17 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
Here the desired matrix is 8x4 or rather the height or width is any multiple of 4. This would mean the nearest greater multiple of 4 if we keep any one dimension(height or width) fixed for fitting all elements and padding the extra elements with zeroes. I have tried reshape like so
reshape([c(:) ; zeros(rem(nc - rem(numel(c),nc),nc),1)],nc,[])
Here c is the original vector or matrix, nc is the number of columns.
It simply changes the number of rows and cols but does not take into account the possible powers required by the condition for height and width. I don't have the Communications Toolbox which has the vec2mat function.
Another possible alternative thought is to initialize a matrix with all zeroes and then assign. But at this point I'm stuck. So please help me matlab experts.
i think this what you mean:
n = 4;
A = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17];
B = zeros(n,ceil(numel(A)/n^2)*n);
B(1:numel(A)) = A;
B = B'
B = [ 1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
17 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0]

finding indeces of similar group elements

I have a vector test2 that includes NaN 0 and 1 in random order (we cannot make any assumption).
test2 = [NaN 1 1 1 0 0 0 NaN NaN NaN 0 0 0 1 1 1 0 1 1 1 ];
I would like to group the elements containing consecutive 1 and to have in the separte vectors start and finish the first and last index of the groups.
In this case start and finish should be:
start = [2 14 18];
finish = [4 16 20];
I tried to adapt the code provided here coming up with this solution that is not working...could you help me with the right solution and tell me why the one I tried doesn't work?
a = (test2 ==1);
d = diff(a);
start = find([a(1) d]==1); % Start index of each group
finish = find([d - a(end)]==-1); % Last index of each group
start =
2 14 18
finish =
2 3 5 6 7 8 9 10 11 12 14 15 18 19
I am using MATLAB R2013b running on Windows.
I tried also using MATLAB R2013a running on ubuntu.
a = (test2 ==1)
d=diff([0 a 0])
start=find(d==1)
finish=find(d==-1)-1
Padding a zero at the beginning and end is the easiest possibility. Then the special cases where a group starts at index 1 or ends at last index don't cause problems.
Full output:
>> test2 = [NaN 1 1 1 0 0 0 NaN NaN NaN 0 0 0 1 1 1 0 1 1 1 ]
test2 =
Columns 1 through 16
NaN 1 1 1 0 0 0 NaN NaN NaN 0 0 0 1 1 1
Columns 17 through 20
0 1 1 1
>> a = (test2 ==1)
a =
Columns 1 through 16
0 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1
Columns 17 through 20
0 1 1 1
>> d=diff([0 a 0])
d =
Columns 1 through 16
0 1 0 0 -1 0 0 0 0 0 0 0 0 1 0 0
Columns 17 through 21
-1 1 0 0 -1
>> start=find(d==1)
start =
2 14 18
>> finish=find(d==-1)-1
finish =
4 16 20
>>
The problem is the line finish = find([d - a(end)]==-1);, in particular that a(end) == 1. There are two steps to correcting this. First, change the problem line to finish = find(d==-1); This tells MATLAB, "Look for the elements where the difference between adjacent elements is -1". In other words, the vector shifts from 1 to 0 or NaN. If you run the code, you'll get
start = 2 14 18
finish = 4 16
Now, you'll notice the last element isn't detected (i.e. we should get finish(3) == 20. This is because the length of d is one less than the length of test2; the function diff cannot calculate the difference between the last element and the non-existant last+1 element!
To remedy this, we should modify a:
a = [(test2 == 1) 0];
And you will get the right output for start and finish.

How to find the indices of nonzero rows in a matrix?

How to find the indices of nonzero rows in a matrix?
Example:
A = [
14 0 6 9 8 17
85 14 1 3 0 99
0 0 0 0 0 0
29 4 5 8 7 46
0 0 0 0 0 0
17 0 5 0 0 49
]
the desired result :
V =[1 2 4 6]
You can use
ix = any(x,2);
any check whether there is any element that is not a zero. The second argument stands for "per-row" computation.
If you want to get the numeric index, you can use find function:
numIx = find(ix);
Another method:
ix = sum(abs(x),2)~=0;
Use
[i,~] = ind2sub(size(A),find(A));
v = unique(i);
Result for the matrix given above:
v = unique(i')
v =
1 2 4 6
Here's one that ab(uses) the fast matrix multiplication in MATLAB -
idx = find(abs(A)*ones(size(A,2),1))

Multiplication of Vectors with diagonal of a matrices from t to t+1 in Matlab

Still very new to programming...
I have 9x1 Vectors at time t, t+1, t+2 etc.
[10 10 10 10 10 10 10 10 10]'
and matrices. Each matrix is 9x9 and also at time 1, t+1, t+2 etc. =
1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 1
They are 3d matrices and I want to make them 4d in the future.
I want to multiply vector(:,:,t) with the diagonal of matrix at time t and output vector(:,:,t+1).
So in short...
vector t multiplied by diag matrix t = vector t+1
vector t+1 multiplied by diag matrix t+1 = vector t+2
vector t+2 multiplied by diag matrix t+2 = vector t+3 ... and so on.
the diagonal numbers change in each time step but for simplicity sake, let's keep them all at 1 for the moment.
I've tried using diag but it states I have to use a 2D input so only works when I ignore t.
Cheers for your help guys - it's helping me learn a lot. Any hints or solutions will be much appreciated. I know you guys know the simplest and most efficient solutions.
Since the result of each step depends on the previous iteration, it cannot be vectorized. So I would go with #JohnColby's solution.
For what it's worth, here is an example how you would extract the diagonals of a 3D matrix in a vectorized way:
M = reshape(1:3*4*3,[3 4 3]);
[r,c,p] = size(M);
ind = bsxfun(#plus, (1:r+1:r*c)', (0:p-1).*r*c);
M(ind)
Each column of the result corresponds to the diagonal elements from each slice (doesn't have to be square matrix):
>> M
M(:,:,1) =
1 4 7 10
2 5 8 11
3 6 9 12
M(:,:,2) =
13 16 19 22
14 17 20 23
15 18 21 24
M(:,:,3) =
25 28 31 34
26 29 32 35
27 30 33 36
>> M(ind)
ans =
1 13 25
5 17 29
9 21 33
Here you go:
n = 10;
% Make sample data
t = zeros(9,1,n);
t(:,1,1) = 1;
T = repmat(diag(ones(9,1)), [1 1 n]);
% Loop though to fill in t based on previous t and T
for i = 2:n
t(:,1,i) = t(:,1,i-1) .* diag(T(:,:,i-1));
end
Now all of t should be 1.