Plot different length cell array without loop - arrays

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.

Related

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.

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

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.

how to eliminate repeating integers from cell array in matlab

i have [words*sentences]matrix where sentences have integers that represent sentence numbers from a text document from this matrix i have constructed 1D array of [1*N] which shows words and in which sentences they occur number wise.
once above step is done i have taken intersection to check which words occur together in which sentences the code is as follows:
OccursTogether = cell(length(Out1));
for ii=1:length(Out1)
for jj=ii+1:length(Out1)
OccursTogether{ii,jj} = intersect(Out1{ii},Out1{jj});
end
end
celldisp(OccursTogether)
the sample output is as follows which shows 1st word occurs in sentence
{5 10 16} same word occurs with 2nd word in sentence {11 12 13} and word 1 occurs with word 3 in sentence {9 14} and so on till the Nth word:
OccursTogether{1,1} = 5 10 16
OccursTogether{2,1} = 5 12 16
OccursTogether{3,1} = 9 14
now what i want is to show output in one line based upon OccursTogether cell array without repeating sentence numbers as below:
output: {5 9 10 12 14 16}
any help would me appreciated..
If I understand correctly:
result = unique([OccursTogether{:}]);
In your example this gives
result =
5 9 10 12 14 16
Here is a way using cellfun and cell2mat. The idea is to vertically concatenate each cell form the cell array, convert it to a matrix and apply the unique function.
So the first step:
a = cellfun(#(x) x.',OccursTogether,'uni',false)
Takes each cell and transpose it, thus making a n x 1 vector. The result is a cell array containing vertical vectors:
a =
[3x1 double]
[3x1 double]
[2x1 double]
Now we can use cell2mat to convert to a numeric matrix since the dimensions will fit and finally apply unique. Otherwise that would not be possible (eg using 1x3 and 1x2 vectors).
In 1 line that looks like this:
output = unique(cell2mat(cellfun(#(x) x.',OccursTogether,'uni',false)))
output =
5
9
10
12
14
16
Hope this is what you meant! If not please tell me.

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