Assuming size_of_array < n, to iterate through array elements multiple times, normally I would use something like (in C++):
for (size_t i = 0; i < n; ++i)
{
elem = arr[ i % size_of_arr ];
}
If arr = {1, 2, 3};, for elem I would get:
1 2 3 1 2 3 ...
However, in MATLAB / Octave indexes start from 1 and:
for i = 1 : n
elem = arr( mod( i, length(arr) + 1) );
end
so when n == length(arr) I get an error:
error: arr(0): subscripts must be either integers 1 to (2^31)-1 or logicals
How is this done when indexes start from 1?
In c++ you would do
arr[ i % size_of_arr]
where the inner index i % size_of_arr is in range [0 size_of_arr-1]
In MATLAB, i is in range [1 size_of_arr], thus just change to
mod( i-1, numel(arr) ) + 1
the first bit (mod( i-1, numel(arr))) makes sure that the index is inside [0 size_of_arr-1], and the you just need to add 1 to that.
Related
I am trying to get M. To do this, it is necessary for Matlab to relate column 1 of A to column 1 of π΅^πand build a matrix M with 1 and 0 depending on whether in position π΄[π,π] and π΅^π[π,π] are equal to 1
A = [1 0 1; 0 1 1; 0 0 1 ];
B = [0 0 1 ; 0 1 0; 1 1 1];
for i = 1:3
for j =1:3
if A(i,j) == BT(i,j) && A(i,j)==1;
Z(i,j) = 1
end
end
end
When you use "if A(i,j) == BT(i,j) && A(i,j)==;" you are comparing individual elements. Instead you want to be comparing columns:
A(:, i) and BT(:, j).
Precisely, you want
for i = 1:3
for j = 1:3
M(i,j) = any( A(:,i) & BT(:,j) );
end
end
OR
You are comparing the columns of BT and the columns of A.
That is to say, the rows of B and the columns of A. You want to see if there are any occasions when both of the elements are 1. Thus you can compare the products of the terms in the rows of B and columns of A.
i.e. M = logical(B * A) should also give you the desired output.
NOTE that the data in B are different in your image examples and in your code.
I've a series of coordinates (i,j) and I want to loop through each one.
For example
A = ones(3,3);
i = [1 2 3];
j = [3 2 1];
I tried with this but it doesn't work:
for (i = i && j = j)
A(i,j) = 0;
end
I also tried this but it doens't work as expected:
for i = i
for j = j
A(i,j) = 0;
end
end
Desired result:
A =
1 1 0
1 0 1
0 1 1
Although A is a matrix in this example, I am working with table data.
The correct syntax to do what you want is:
A = ones(3,3);
i = [1 2 3];
j = [3 2 1];
for ii = 1:length( i )
A( i(ii) , j(ii) ) = 0;
end
Essentially you loop through each element and index i and j accordingly using ii. ii loops through 1..3 indexing each element.
This will give the a final result below.
>> A
A =
1 1 0
1 0 1
0 1 1
While this works and fixes your issue, I would recommend rayryeng's alternate solution with conversions if you don't have more complex operations involved.
Though this doesn't answer your question about for loops, I would avoid using loops all together and create column-major linear indices to access into your matrix. Use sub2ind to help facilitate that. sub2ind takes in the size of the matrix in question, the row locations and column locations. The output will be an array of values that specify the column-major locations to access in your matrix.
Therefore:
A = ones(3); i = [1 2 3]; j = [3 2 1]; %// Your code
%// New code
ind = sub2ind(size(A), i, j);
A(ind) = 0;
Given that you have a table, you can perhaps convert the table into an array, apply sub2ind on this array then convert the result back to a table when you're done. table2array and array2table are useful tools here. Given that your table is stored in A, you can try:
Atemp = table2array(A);
ind = sub2ind(size(Atemp), i, j);
Atemp(ind) = 0;
A = array2table(Atemp);
I have a matrix M that looks similar to this:
M = [ 1, 2, 3, 0, 0;
1, 2, 0, 0, 0;
2, 3, 4, 5, 0;
4, 5, 6, 0, 0;
1, 2, 3, 4, 5;
]
I'm trying to get a column vector with the rightmost non-zero value of each row in A, but ONLY for the rows that have the first column == 1.
I'm able to calculate a filter for the rows:
r = M( :, 1 ) == 1;
> r = [ 1; 1; 0; 0; 1 ]
And I have a set of indices for "the rightmost non-zero value of each row in M":
> c = [ 3, 2, 4, 3, 5 ]
How do I combine these in a slicing of A in order to get what I'm looking for? I'm looking for something like:
A( r, c )
> ans = [ 3; 2; 5 ]
But doing this gets me a 3x3 matrix, for some reason.
The shortest way I can think of is as follows:
% Get the values of the last non-zero entry per row
v = M(sub2ind(size(M), 1:size(M,1), c))
% Filter out the rows that does not begin with 1.
v(r == 1)
This seems to work (I assume other operations defining r,c have been performed):
M(sub2ind(size(A),find(r==1).',c(r==1))).'
Short interpretation of the problem and solution:
M( r, c )
gives a 3 x 5 matrix (not 3 x 1 as desired) due to mixing of logical and subscript indices. The logical indices in r pick out rows in A with r==1. Meanwhile row array c picks out elements from each row according to the numeric index:
ans =
3 2 0 3 0
0 2 0 0 0
3 2 4 3 5
What you really want are indices into the rightmost nonzero elements in each row starting with 1. The solution uses linear indices (numeric) to get the correct elements from the matrix.
I think this should do the trick. I wonder if there is more elegant way of doing this though.
% get only rows u want, i.e. with first row == 1
M2 = M(r,:);
% get indices of
% "the rightmost non-zero value of each row in M"
% for the rows u want
indicesOfinterest = c(r==1);
noOfIndeciesOfinterest = numel(indicesOfinterest);
% desired output column vector
output = zeros(noOfIndeciesOfinterest, 1);
% iterate through the indeces and select element in M2
% from each row and column indicated by the indice.
for idx = 1:noOfIndeciesOfinterest
output(idx) = M2(idx, indicesOfinterest(idx));
end
output % it is [3; 2 ; 5]
You can use
arrayfun(#(x) M(x,c(x)), find(r))
But unless you need r and c for other purposes, you can use
arrayfun(#(x) M(x,find(M(x,:),1,'last')), find(M(:,1)==1))
Here is a way to do it using linear indexing:
N = M';
lin_index = (0:size(N,1):prod(size(N))-1) + c;
v = N(lin_index);
v(r)
I have a matrix M(x,y). I want to apply a threshold in all values in x, such that if x
Example:
M = 1, 2;
3, 4;
5, 6;
If t = 5 is applied on the 1st dimension, the result will be
R = 0, 2;
0, 4;
5, 6;
One way (use M(:,1) to select the first column; M(:,1)<5 returns row indices for items in the first column that are lest than 5))-
> R = M;
> R(M(:,1)<5,1) = 0
R =
0 2
0 4
5 6
Another -
R = M;
[i,j]=find(M(:,1)<5); % locate rows (i) and cols (j) where M(:,1) < 5
% so j is just going to be all 1
% and i has corresponding rows
R(i,1)=0;
To do it in a matrix of arbitrary dimensions:
thresh_min = 5;
M(M < thresh_min) = 0;
The statement M < thresh_min returns indices of M that are less than thresh_min. Then, reindexing into M with these indices, you can set all of these valuse fitting your desired criterion to 0 (or whatever else).
I want to calculate the sum of the elements in a matrix that are divisible by 2. How do I do it? And how do I output the answer in a co-ordinate form?
If you have a matrix M, you can find a logical index (i.e. mask) for where the even elements are by using the MOD function, which can operate on an entire matrix without needing loops. For entries in the matrix that are even the remainder will be 0 after dividing by 2:
index = (mod(M,2) == 0);
You can get the row and column indices of these even entries using the function FIND:
[rowIndices,colIndices] = find(index);
And you can get the sum of the even elements by indexing M with the logical mask from above to extract the even entries and using the SUM function to add them up:
evenSum = sum(M(index));
Here's an example with a matrix M created using the function MAGIC:
>> M = magic(3)
M =
8 1 6
3 5 7
4 9 2
>> index = (mod(M,2) == 0)
index =
1 0 1 %# A matrix the same size as M with
0 0 0 %# 1 (i.e. "true") where entries of M are even
1 0 1 %# and 0 (i.e. "false") elsewhere
>> evenSum = sum(M(index))
evenSum =
20
This is the matrix M with only its even values:
(mod(M,2) == 0).*M
You can sum it with sum(M) or sum(sum(M)) (not sure what "co-ordinate form" means).
Some pseudo-code. Pretty much loop through each column for each of the rows.
sum = 0
for(i = 0; i < matrix.num_rows; i++) {
for(j = 0; j < matrix.num_cols; j++) {
if(matrix[i][j] % 2 == 0)
sum += matrix[i][j]
}
}
Not sure what you mean by Coordinate form though.