This question already has answers here:
MATLAB - extracting rows of a matrix
(5 answers)
Closed 7 years ago.
Can someone explain to me the solution of this exercise:
Exercise
Write a function called odd_index That Takes a matrix, M, as input argument and returns a matrix That contains only elements of M Those That are in odd rows and columns. In other words, it would return the elements of M at indices (1,1), (1,3), (1,5), ..., (3,1), (3,3), (3,5) , …, etc. That note both the row and the column of an element must be odd to be included in the output. The following would not be returned: (1,2), (2,1), (2,2) Because Either the row or the column or both are even. As an example, if M Were a 5-by-8 matrix, the output must be then a 3-by-4 Because the function omits rows 2 and 4 of M and it omits Also columns 2, 4, 6, and 8 of M .
Solution:
M_out = odd_index function (M)
M_out = M (1: 2: end, 1: 2: end);
end
Link solution: Return only odd elements
Can someone explain to me how they came to the function M_out = M (1: 2: end, 1: 2: end) ;.
function M_out = odd_index (M)
M_out = M(1: 2: end, 1: 2: end);
end
I takes each odd element of the matrix M and returns that to a matrix M_out,
M = [1 2 3; 4 5 6;7 8 9];
M_out = odd_index(M)
M_out =
1 3
7 9
where you can see that elements on an odd row and on an odd column are being printed, but the elements on even rows and even columns are being left out.
The trick here is to step through the indices in steps of 2 instead of 1. M(1,1) gives the element in the upper-left corner of M, i.e. 1. M(1:2,1) returns the first two elements in the left column: 1 and 4. This happens because n:m creates a vector of numbers running from n to m in steps of 1. You can change this step size by adding a number: n:x:m, where x specifies how large your steps are. Since the odd numbers are 2 apart, just start your vector at the lowest, positive, odd number, 1, and step with size 2. The last element in your vector 1:2:end simply means "the end of the vector", thus, if M = [5x3] the end of the rows is 5, because there are five rows, and the end of the columns would be 3, since there are three columns.
Related
I have a matrix where each element is a single unit of a 2d coordinate. As such, each element in any given row are paired, where elements in the first column are paired with those in the second, and elements in the third column paired with the fourth. All possible combinations of the 4 numbers are present in the matrix.
What I need to do is depup the matrix by removing rows where the first set of coordinates (e.g columns 1 and 2 in a row) are swapped with the second set of coordinates. For example if one row contains the value "3, 4, 2, 1" then I would need to remove "2, 1, 3, 4" from else where in the matrix.
An example of this could be seen below, where I would want to remove the last row, as it is the reverse of the first row;
3 3 1 1
1 2 2 3
3 4 1 2
4 4 3 1
4 1 4 4
1 1 3 3
I'm quite stumped as to how to do this, and my previous attempts have all failed. Whilst it may not be useful to the answer, I have included my code showing how I am constructing the initial matrix below;
%create list of all piece coordinates
p1_row_index=(1:n);
p1_column_index=(1:n);
p2_row_index=(1:n);
p2_column_index=(1:n);
% get all possible combinations of these variables
[p1_row_index,p1_column_index,p2_row_index,p2_column_index]=BalanceFactors(1,1,1:n,1:n,1:n,1:n);
pc_list(:,1)=p1_row_index; % piece1 coordiantes for rows
pc_list(:,2)=p1_column_index; % piece1 coordiantes for columns
pc_list(:,3)=p2_row_index; % piece2 coordiantes for rows
pc_list(:,4)=p2_column_index; % piece2 coordiantes for columns
Thank you for your time.
Many thanks,
Matt
Complex numbers come in handy for this:
[~, ind] = unique(sort(M(:,[1 3])+1j*M(:,[2 4]), 2), 'rows', 'stable');
result = M(ind, :);
The code works as follows:
M(:,[1 3])+1j*M(:,[2 4]) creates a complex matrix with half the columns, where each pair of coordinates of the original matrix becomes a complex number.
sort(..., 2) sorts each row. Rows that originally were shuffled versions of each other now become identical.
[~, ind] = unique(..., 'rows', 'stable') gives the index of the first occurrence of each unique (complex, sorted) row.
M(ind, :) selects the desired rows from M.
Suppose I have a matrix in MATLAB.
>> m = [1 2 3; 4 5 6; 7 8 9]
m =
1 2 3
4 5 6
7 8 9
I have a list of indices, and I would like elements at those indices to be removed from the matrix.
The indices may belong to any arbitrary row or column. However, I can guarantee that if I were to remove an element from a row, I must remove an element from all other rows.
Once all the elements are removed, any "gaps" in the matrix should be addressed by shifting elements to the left.
% for example, removing m(1, 1), m(2, 2), m(3, 3) should yield
m =
2 3
4 6
7 8
% it will NOT yield the following because the elements were shifted up, not to the left.
M =
4 2 3
7 8 6
% removing only m(1, 1) would also be invalid,
% because I must remove an element from all other rows.
What would be the most efficient way to perform this operation for arbitrary number of indices?
As you need the elements shifted up, the solution is a two-step one. First transpose the matrix, remove the corresponding elements, and then reshape and transpose the result. (If shifting up were allowed, then you wouldn't need to transpose). Assuming the indices are stored in a matrix, remove, then:
m=[1,2,3;4,5,6;7,8,9];
remove=[1,1;2,2;3,3];
copy=m.';
width=size(copy,2);
copy(sub2ind(size(copy),remove(:,2),remove(:,1)))=[];
m=reshape(copy,[],width).'
I think that solves the problem...
Good day,
I have a question what I want to achieve without the loop if possible. As title says I need to do windowed subtraction of vectors that are not same size and then finding the mean of results.
As example, let say that we have vector a = [2 3 4 5 6] and vector b = [1 2].
Program will have to move window with smaller numbers of elements (in this example vector b) over bigger one (vector a) and make operations on that way so it starts in first two elements in vector a and make subtraction with vector b and then sum results and find mean.
In this example it will just make calculation of subtraction 2-1 = 1, 3-2 = 1, summing results 1+1=2 and divide them with 2 (because vector b is that size). Final result is 1.
Then we move window on second elements of vector a (value 3 and 4 there, or index 2 and 3) and repeat process to the last elements of vector a.
For final result we need to get vector c who consist of elements [1 2 3 4] for this example.
Is this possible to do without looping because I have data sets over 10k of size. Thanks in advance
I can solve it with only one loop, iterating through "b" (two loops in your example).
Declare vectors (as columns! This is needed for matlabs computations to work)
a = [2 3 4 5 6]';
b = [1 2]';
Declare matrix for computed results. Each column represents subtractions of elements in "a" with one of the elements in "b".
c = zeros(length(a)-length(b)+1,length(b));
for k = 1:length(b)
c(:,k) = a(k:length(a)-length(b)+k)-b(k);
end
Now just sum the elements in "c" row wise and divide by length of "b" to get the mean
result = sum(c,2)/length(b);
You can simplify this for your exact example, but this is a generic solution for any vetors "a" and "b", where "b" is the smaller vector.
I have a 10x10 matrix called A:
I have vector of column numbers:
C = [ 2, 6, 8 ];
I have a vector of row numbers:
R = [1; 3; 7];
The column numbers correspond to each row. i.e. For column 1 we are looking at row numbers given by R, for column 3 we are looking at row numbers given by R and so on.
I want to replace those exact locations in A with some other number 13.
i.e. for each of these locations in matrix A:
(1,2) (1,6) (1,8), (3,2), (3, 6), (3,8) I want to insert 13.
How do I achieve the above ?
you can do A(R,C) = 13 .......
As dlavila pointed out, you can do A(R,C) = 13 wich would be the best and easiest. Nevertheless I have written a longer code involving the eval function that you might find useful in the future:
for ii=1:length(C)
for jj =1:length(R)
eval(strcat('A(', num2str(C(ii)), ',',num2str(R(jj)),')=13;'))
end
end
Both give the same results.
Say I have a matrix
A = [1, 2, 3; 4 5 6; 7 8 9]
If I want to choose say (1,2), (2,3)
I could not say A(1:2,2:3) otherwise it will return a 2*2 matrix, what should I do it for only one time...
Use sub2ind to linearly index (to avoid creating a matrix) using the given row and column numbers -
ind = [1,2;2,3]
A(sub2ind(size(A),ind(:,1),ind(:,2)))