How to use a loop in this case? - matlab

I have 3 matrices,
test_1=[1 2 3; 4 5 6; 7 8 9; 10 11 12; 13 14 15; 16 17 18];
test_2=[16 18 15; 6 5 8; 2 9 5; 11 19 21; 22 28 30; 14 16 19];
test_3=[11 9 7; 8 22 17; 27 31 30; 28 26 40; 66 57 36; 82 21 19];
I want to save all the elements of first two rows as,
firstrow_test_1= test_1([1; 2],:);
firstrow_test_2= test_2([1; 2],:);
firstrow_test_3= test_3([1; 2],:);
These matrices will give the result of all the elements of first two rows of test_1,test_2,test_3.
Then I want to take the 3rd and 4th row of test_1,test_2 and test_3 and save the elements in another set of metrices.
secondrow_test_1= test_1([3; 4],:);
secondrow_test_2= test_2([3; 4],:);
secondrow_test_3= test_3([3; 4],:);
Similarly for the rest, I have to do,
thirdrow_test_1= test_1([5; 6],:);
thirdrow_test_2= test_2([5; 6],:);
thirdrow_test_3= test_3([5; 6],:);
If I do this way then the code will be very long. So is there any way to write the code in a shorter way? Can anybody please help me to use a loop in this case,if it is possible?
What if we have 50 matrices like test_1,test_2,...,test_50 and we want to do the same in that case? (save the first 2 rows in another matrix,then the next 2 rows in another matrix..etc)
Thanks.

This is MatLab (Matrix Laboratory). you need to make use of multiple dimensions of a matrix to store the data instead of creating separate variables, if they all are of same dimensions (as in your case). Else if their dimensions are not same, you could use cell arrays.
Here are some links which might help you.
Multidimensional Arrays
Cell Arrays
Taking your example (see how easily you could solve your problem with use of nD matrices)
%// creating multidimensional matrix from those 2D matrix
A = cat(3,test_1, test_2, test_3); %// stacking each 2D slices in 3rd dimension
for example,
firstrow_test_1 could be accessed by using A(1:2,:,1).
Similarly,
firstrow_test_2 could be accessed by using A(1:2,:,2)
and so on.. I hope you got an idea.
Here i created a 3D matrix from the 2D slices as you had them as 2D slices. But you should be able to create 3D matrices directly and the same process could be applied.

Related

Fraction of overlapping members across multiple vectors

I have a cell M with n number of cells, with each cell containing several unique numbers, something like this:
{[15 16 21 26 28 145],[2 5 8 9 15],[20 24 27],[10 11 15 8 6 258 74 1],...}
Some of these values appear in more than 1 cell. I would like to calculate the fraction of overlapping values across these cells. For instance, with the 4 cells above, I have 19 unique numbers, and 2 of them belong to more than 1 cell: 15 and 8. Thus, the fraction of overlapping cell is 2/19 = .105. Note that the number of cells in M can vary and thus the number of unique numbers in M also vary as well. Does anyone have any suggestion on how to do this efficiently? I've tried horzcat to concatenate the cells within M then used unique but didn't quite get what I want.
Using the output of the hist() function is useful here.
M = {[15 16 21 26 28 145],[2 5 8 9 15],[20 24 27],[10 11 15 8 6 258 74 1]};
% Bring data to one matrix.
M2 = cell2mat(M);
% Build a histogram from the data with a bin on each unique element. The
% first output of hist is the number of elements in each bin.
a = hist(M2,unique(M2));
% Calculate the overlap by dividing the number of elements that occur more
% than once by the total number of elements.
overlap = sum(a>1)/numel(a);

MATLAB APPLY CUMSUM IN STEPS

I have data of integers in x = 500 X 612 matrix. I need a new variable xx in a 500 X 612 matrix but I need to apply cumsum along each row (500) across 12 column steps and applying cumsum like this 51 times --> 500 X (12 X 51) matrix. Then I need a for loop to produce 51 plots of the 500 rows and 12 columns of the cumsum time series. thank you!
I will rephrase what the question is asking to benefit those who are reading.
The OP wishes to segment a matrix into chunks by splitting up the matrix into a bunch of columns. A cumsum is applied to each row individually for each column and are then concatenated together to build a final matrix. As such, given this source matrix:
x =
1 2 3 4 5 6 7 8 9 10 11 12
13 14 15 16 17 18 19 20 21 22 23 24
Supposing that we wish to split up the matrix by columns 3, 6 and 9 and 12, we will have four chunks to work with. We do a cumsum on each of these blocks individually and piece the final result together. So the result would like the following:
xx =
1 3 6 4 9 15 7 15 24 10 21 33
13 27 42 16 33 51 19 39 60 22 45 69
First, you need to determine how many columns you want to break up the matrix into. In your case, we wish to segment the matrix into 4 chunks: Columns 1 - 3, columns 4 - 6, columns 7 - 9, and columns 10 - 12. As such, I'm going to reshape this matrix so that each column is an individual row from a chunk in this matrix. We then apply cumsum over this reshaped matrix and we then reshape it back to what you had originally.
Therefore, do this:
num_chunks = 4; %// Columns 3, 6, 9, 12
divide_point = size(x,2) / num_chunks; %// Determine how many elements are in a row for a cumsum
x_reshape = reshape(x.', divide_point, []); %// Get reshaped matrix
xy = cumsum(x_reshape); %// cumsum over all columns individually
xx = reshape(xy, size(x,2), size(x,1)).'; %// Reconstruct matrix
In the third line of code, x_reshape = reshape(x.', divide_point, []); may seem a bit daunting, but it's actually not that bad. I had to transpose the matrix first because you want to take each row of a chunk and place them into individual columns so we can perform a cumsum on each column. When you reshape something in MATLAB, it collects values column-wise and reshapes the input into an output of a specified size. Therefore, to collect the rows, we need to collect row-wise and so we must transpose this matrix. Next, divide_point tells you how many elements we have for a single row in one chunk. As such, we want to construct a matrix that is of size divide_point x N where divide_point tells you how many elements we have in a row of a chunk and N is the total number of rows over all chunks. Because I don't want to calculate how many there are (am rather lazy actually....), the [] syntax is to automatically infer this number so that we can get a reshaped matrix that respects the total number of elements in the original input. We then perform cumsum on each of these columns, and then we need to reshape this back into the original shape of the input. With this, we use reshape again on the cumsum result, but in order to get it back into the row-order that you want, we have to determine the transpose as reshape takes values in column-major order, then re-transpose that result.
We get:
xx =
1 3 6 4 9 15 7 15 24 10 21 33
13 27 42 16 33 51 19 39 60 22 45 69
In general, the total number of elements to sum over for a row needs to be evenly divisible by the total number of columns that your matrix contains. For example, given the above, if you were to try to segment this matrix into 5 chunks, you would certainly get an error as the number of rows to cumsum over is not symmetric.
As another example, let's say we wanted to break up the matrix into 6 chunks. Therefore, by setting num_chunks = 6, we get:
xx =
1 3 3 7 5 11 7 15 9 19 11 23
13 27 15 31 17 35 19 39 21 43 23 47
You can see that cumsum restarts at every second column, as we desired 6 chunks and to get 6 chunks with a matrix of 12 columns, a chunk is created at every second column.

how to find the middle elements of sub matrices in a matrix

I have a matrix and i want to consider it has 4 sub matrices which are placed together. How can I find the middle element of each sub matrix when they are together?
consider the matrix below. It is built by 4 sub matrices.
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
25 26 27 28 29 30
31 32 33 34 35 36
I want to get their middle elements so i could have:
8, 11, 26, 29
From what I have understood this might work for you and this is a demo, so use your own parameters -
Code
%%// Input matrix
A = rand(44,44);
%%/ Number of submatrices needed
num_submat = 16;%%// 4 for your example case
%%/ Number of submatrices along row and column
num_submat1= sqrt(num_submat);
%%// Middle element indices along each direction
v1 = floor(size(A,2)/(2*num_submat1))+1:size(A,2)/(num_submat1):size(A,2);
%%// Middle elements
middle_ele = A(v1,v1)
It is always helpful to know that matrix indexing in matlab goes columnwise eg,
indOrd = [1,4,7;2,5,8;3,6,9]
where the number is the index order and not related to your example. indOrd(4) would return 4. Try to use this to find the index locations.
Assuming that each submatrix has odd size 2n+1, the coordinates of the center of one submatrix alone are [n+1, n+1]. If your have a square with M*M submatrices (M=2 in your case), the coordinates are [n+1+i*(2*n+1), n+1+j*(2*n+1)], i and j taken independently in the range 0:M-1.
Turning back to Matlab, it is now quite easy to generate all indices of the centers of the submatrices grouped in the matrix A:
n = floor(size(A,1)/(2*M));
xc = n+1+reshape(repmat(0:M-1,M,1),[],1);
yc = n+1+reshape(repmat((0:M-1)',1,M),[],1);
centers = A(yc, xc);
For even-sized submatrix, you have to choose which element is the center, the modification is quite easy to do then.

Removing a row in a matrix, by removing an entry from a possibly different row for each column

I have a vector of values which represent an index of a row to be removed in some matrix M (an image). There's only one row value per column in this vector (i.e. if the image is 128 x 500, my vector contains 500 values).
I'm pretty new to MATLAB so I'm unsure if there's a more efficient way of removing a single pixel (row,col value) from a matrix so I've come here to ask that.
I was thinking of making a new matrix with one less row, looping through each column up until I find the row whose value I wish to remove, and "shift" the column up by one and then move onto the next column to do the same.
Is there a better way?
Thanks
Yes, there is a solution which avoids loops and is thus faster to write and to execute. It makes use of linear indexing, and exploits the fact that you can remove a matrix entry by assigning it an empty value ([]):
% Example data matrix:
M = [1 5 9 13 17
2 6 10 14 18
3 7 11 15 19
4 8 12 16 20];
% Example vector of rows to be removed for each column:
vector = [2 3 4 1 3];
[r c] = size(M);
ind = sub2ind([r c],vector,1:c);
M(ind) = [];
M = reshape(M,r-1,c);
This gives the result:
>> M =
1 5 9 14 17
3 6 10 15 18
4 8 11 16 20

How to extract all sub-matrices of a bigger one

I have a matrix say:
Q = [05 11 12 16 25;
17 18 02 07 10;
04 23 20 03 01;
24 21 19 14 09;
06 22 08 13 15]
I would like to list out all the possible 3x3 matrices. Some examples are:
11 12 16;
18 2 7;
23 20 3
and
5 11 12;
17 18 2;
4 23 20;
etc.. Basically all the possible 3-by-3 matrices.
How do I do it? I must use a for loop?
If you have the Image Processing Toolbox, you can use the function IM2COL:
subMats = im2col(Q,[3 3]);
Each column of subMats contains the elements of a 3-by-3 matrix extracted from Q. Each of these columns can be reshaped into a 3-by-3 matrix as follows:
Q1 = reshape(subMats(:,1),[3 3]); %# Reshape column 1 into a 3-by-3 matrix
I'm guessing this is homework (if not, please forgive me), so here are some hints.
Draw out the structure of your 5x5 matrix.
Start in the upper left and draw a 3x3 submatrix within that 5x5. What are the elements covered by that matrix?
Go to the upper right. What elements are covered there?
Now go to the lower left. What about there?
Do you see how to cover the whole thing?