How to plot a 2D plot in MATlab from Three Matrices and an array? - arrays

I am trying to plot a figure using three matrices but somehow I couldn't understand. I have three matrices and an array. Suppose,
A =
1 2 3
4 5 4
7 8 9
B =
2 3 13
5 11 10
9 7 6
C =
1 2 3
2 3 13
5 11 10
and an array
Y= [0.001 0.0002 0.0004].
Now I want to plot it in such a way that array values should be on y axis while against 0.001, 0.002 and 0.0004 the matrices value should be arranged.
for examples, the y=0.001, A(1,1)=1, y=0.0002, B(1,1)=2 y=0.0004, C(1,1)=1 for a single line.
and similarly process goes for A(i,j),B(i,j) and c(i,j) points using loop to plot all lines on a single figure.
Thanks

So, the first plot is plot([1,2,1],Y), the next one is plot([2,3,2],Y) and so on?
If so, you could do it like that
X = cat(3,cat(3,A,B),C);
X = reshape(permute(X,[3,1,2]),3,9);
plot(X,Y,'--x');
which gives a plot like this:
Is this what you were looking for? If not, I didn't understand your question well and I'd like to ask you to rephrase it.

You can create a 3D array (tensor) and access it in a loop.
T(:,:,1) = A;
T(:,:,2) = B;
T(:,:,3) = C;
figure;
for idi = 1:size(A,1)
for idj = 1:size(A,2)
plot(squeeze(T(idi,idj,:)).',Y); hold on;
end
end
Accessing the third dimension is not fastest operation (as they are not store sequential in memory) and if the matrices are larger you might consider reshape.
I did not understand you wanted the vector Y to be on the x-axis or y-axis (and neither of those plots make sense to me) but I am sure you can modify the code from here for your needs.

Related

MATLAB: Does there exist a smart way to remove adjacent (x,y) points stored in some array?

Does there? I am thinking specifically about some matrix array where the rows correspond to x and y coordinates, e.g.
4 3
4 5
5 4
3 4
4 4
such that (4,3) and (4,5) etc. are (x,y) points. The problem is this: If one of the points in the list is surrounded adjacently by other points in the list, e.g.
(~,~) (4,5) (~,~)
(3,4) (4,4) (5,4)
(~,~) (4,3) (~,~)
as would be the case for the list above, then I would like to remove it in some efficient manner. It is very easy to see visually if this is satisfied by some point, but how do I do it in code? I am just looking for some suggestions, so if someone has encountered this problem before or have some input I would appreciate to read it!
Best regards,
I'm not sure if you can avoid looping here (not sure if that's what you meant by efficient anyway...). At least i didn't come up with a solution without loops off the top of my head but this should do it.
vec = [4 3; 4 5; 5 4; 3 4; 4 4; 6 7; 6 8; 6 6; 5 7; 7 7];
for i = 1:length(vec)
point = vec(i,:);
mat = vec-point;
% Calculate diagonal values of the matrix product
% Note that sum(mat.*mat,2) might be a bit faster. You can try yourself.
tmp = diag(mat*mat');
if (length(find(tmp == 1)) == 4)
% If we find 4 values of 1 in tmp, the point is surrounded
% E.g., remove the value here if you wish
point
end
end
edit: Also, note that this won't work properly if you have duplicate points in the vector.

Mean values of a matrix in a matrix on Matlab

This is about matlab.
Let's say I have a matrix like this
A = [1,2,3,4,5;6,7,8,9,10;11,12,13,14,15]‍
Now I want to know how to get a mean value of a small matrix in A.
Like a mean of the matrix located upper left side [1,2;6,7]
The only way I could think of is cut out the part I want to get a value from like this
X = A(1:2,:);
XY = X(:,1:2);
and mean the values column wise Mcol = mean(XY);.
and finally get a mean of the part by meaning Mcol row-wise.
Mrow = mean(Mcol,2);
I don't think this is a smart way to do this so it would be great if someone helps me make it smarter and faster.
Your procedure is correct. Some small improvements are:
Get XY using indexing in a single step: XY = A(1:2, 1:2)
Replace the two calls to mean by a single one on the linearized submatrix: mean(XY(:)).
Avoid creating XY. In this case you can linearize using reshape as follows: mean(reshape(A(1:2, 1:2), 1, [])).
If you want to do this for all overlapping submatrices, im2col from the Image Processing Toolbox may be handy:
submatrix_size = [2 2];
A_sub = im2col(A, submatrix_size);
gives
A_sub =
1 6 2 7 3 8 4 9
6 11 7 12 8 13 9 14
2 7 3 8 4 9 5 10
7 12 8 13 9 14 10 15
that is, each column is one of the submatrices linearized. So now you only need mean(A_sub, 1) to get the means of all submatrices.

Plot different length cell array without loop

I have the following output from a code:
MAT_ArrayT - 6x1 cell
MAT_ArrayY - 6x1 cell
Inside each of the it looks as following:
10000x1 double
9000x1 double
8000x1 double
7000x1 double
6000x1 double
5000x1 double
I would like to have a plot where I get 6 lines that fit to each other.
The result I want to get is as follows:
for i = 1:6
plot(MAT_ArrayT{i,:},MAT_ArrayY{i,:})
end
but without for loop since it takes much longer where I need to draw 1k+ lines.
Thank you.
The quick-and-dirty solution is as in my answer to your previous question, padding the shorter vectors with NaN. NaN points are not plotted.
If you hand Matlab's plot function an array, it will plot each column of the array as it's own line. For example:
A = 1:2:20;
B = 1:10;
C = [A', B']
plot(C)
Produces
C =
1 1
3 2
5 3
7 4
9 5
11 6
13 7
15 8
17 9
19 10
As we can see, plot() has plotted the first column of C as the blue line, and the second column of C as the orange line, and we did it with just one line of code. If you can set up your cell arrays such that each line you want to plot is its own column, this should be able to speed things up for you.

Given 2 positions (x1,y1) and (x2,y2) print the sum of all elements within the area of rectangle in O(1) time

A 2D matrix is given to you. Now user will give 2 positions (x1,y1) and (x2,y2),
which is basically the upper left and lower right coordinate of a rectangle formed within the matrix.
You have to print sum of all the elements within the area of rectangle in O(1) running time.
Now you can do any pre computation with the matrix.
But when it is done you should answer all your queries in constant time.
Example : consider this 2D matrix
1 3 5 1 8
8 3 5 3 7
6 3 9 6 0
Now consider 2 points given by user (0, 2) and (2, 4).
Your solution should print: 44.
i.e., the enclosed area is
5 1 8
5 3 7
9 6 0
Since your question seems to be related to homeworks, i am just posting a clue... It is a formula that may inspire you :
What does this sum of terms represent ?
Rewrite your problem using mathematical tools, indexes like i and j ...
maybe this can also help:
courtosy of: http://www.techiedelight.com/calculate-sum-elements-sub-matrix-constant-time/

Easiest way to create arrays based on repeating character positions

I want to group my elements using the repeated segments in the array. The breaking is basically depend on where the repeated segments are, in my real data contains ~10000 elements and I want to know if there is a easier way to do that.
Here is a short example to clarify what I want:
Let's say I have an array,
A=[1 5 3 4 4 4 6 9 8 8 9 5 2];
What I want is to break A into [1 5 3],[6 9], and [9 5 2];
What is the easiest to code this using matlab??
Thanks.
For a vectorized solution, you can find out the places where either forward or backward differences to the neighbor are zero, and then use bwlabel (from the Image Processing Toolbox) and accumarray to gather the data.
A=[1 5 3 4 4 4 6 9 8 8 9 5 2];
d = diff(A)==0;
%# combine forward and backward difference
%# and invert to identify non-repeating elments
goodIdx = ~([d,false]|[false,d]);
%# create list of group labels using bwlabel
groupIdx = bwlabel(goodIdx);
%# distribute the data into cell arrays
%# note that the first to inputs should be n-by-1
B = accumarray(groupIdx(goodIdx)',A(goodIdx)',[],#(x){x})
EDIT
Replace the last two lines of code with the following if you want the repeating elements to appear in the cell array as well
groupIdx = cumsum([1,abs(diff(goodIdx))]);
B = accumarray(groupIdx',A',[],#(x){x})
EDIT2
If you want to be able to split consecutive groups of identical numbers as well, you need to calculate groupIdx as follows:
groupIdx = cumsum([1,abs(diff(goodIdx))|~d.*~goodIdx(2:end)])
Here is a solution that works if I understand the question correctly. It can probably be optimised further.
A=[1 5 3 4 4 4 6 9 8 8 9 5 2];
% //First get logical array of non consecutive numbers
x = [1 (diff(A)~=0)];
for nn=1:numel(A)
if ~x(nn)
if x(nn-1)
x(nn-1)=0;
end
end
end
% //Make a cell array using the logical array
y = 1+[0 cumsum(diff(find(x))~=1)];
x(x~=0) = y;
for kk = unique(y)
B{kk} = A(x==kk);
end
B{:}

Resources