Plotting only parts of vector - matlab

I have a vector like this:
a = [1 2 0 0 3 4 0 5]
I wanna plot this vector but getting rid of the Os. So, I tried this:
> b = (a>0);
> c = a(b);
> plot(c);
The plot is just fine bit I'm not happy with the time axis. On the time axis, I have now consecutive steps; but I want it to be the corresponding time steps from a to the values i plot from c. So, in this case, my timeline should look like this:
> [1 2 5 6 8]
Any ideas?

Simply define a variable with your t and use the filter on it as well
a= [1 2 0 0 3 4 0 5]
t = 1:length(a)
idx=(a>0);
plot(t(idx), a(idx));

Set the undesired values of a to NaN, and plot ignores them and interjects the line where NaN occurs.
a(a==0)=NaN

find() does exactly what you want, return the index of every nonzero value.
a= [1 2 0 0 3 4 0 5];
b=find(a);
plot(b,a(b))
If you only want positive values, you also hook that into find:
b=find(a>0);

Related

MATLAB: After reshaping matrix to array, how can we know back where the value originally belongs to?

Let z = [1 3 5 6] and by getting all the difference between each elements:
we get:
bsxfun(#minus, z', z)
ans =
0 -2 -4 -5
2 0 -2 -3
4 2 0 -1
5 3 1 0
I now want to order these values in ascending order and remove the duplicates. So:
sort(reshape(bsxfun(#minus, z', z),1,16))
ans =
Columns 1 through 13
-5 -4 -3 -2 -2 -1 0 0 0 0 1 2 2
Columns 14 through 16
3 4 5
C = unique(sort(reshape(bsxfun(#minus, z', z),1,16)))
C =
-5 -4 -3 -2 -1 0 1 2 3 4 5
But by looking at -5 in [-5 -4 -3 -2 -1 0 1 2 3 4 5],
how can I tell where -5 comes from. By reading myself the matrix,
0 -2 -4 -5
2 0 -2 -3
4 2 0 -1
5 3 1 0
I know it comes from z(1) - z(4), i.e. row 1 column 4.
Also 2 comes from both z(3) - z(2) and z(2) - z(1), which comes from two cases. Without reading the originally matrix itself, how can we know that the 2 in [-5 -4 -3 -2 -1 0 1 2 3 4 5] is originally in row 3 column 2 and row 2 column 1 of the original matrix?
So by looking at each element in [-5 -4 -3 -2 -1 0 1 2 3 4 5], how do we know, for example, where -5 comes from in the original matrix index efficiently. I want to know as I need to do operation on ,e.g.,-5 and two indices that produce this: for example, for each difference, say -5, i do (-5)*1*6, as z(1)- z(6) = -5. But for 2, I need to do 2*(3*2+2*1) as z(3) - z(2) = 2, z(2) - z(1) = 2 which is not distinct.
Thinking hard, I think i should not reshape bsxfun(#minus, z', z) to array. I will also create two index array such that I can do operations like (-5)*1*6 stated above effectively. However, this is easier said than done and I also have to take care of nondistinct sources. Or should I do the desired operations first?
Use the third output from unique. And don't sort, unique will do that for you.
[sortedOutput,~,linearIndices] = unique(reshape(bsxfun(#minus, z', z),[1 16]))
You can reconstruct the result from bsxfun like so:
distances = reshape(sortedOutput(linearIndices),[4 4]);
If you want to know where a certain value appears, you write
targetValue = -5;
targetValueIdx = find(sortedOutput==targetValue);
linearIndexIntoDistances = find(targetValueIdx==linearIndices);
[row,col] = ind2sub([4 4],linearIndexIntoDistances);
Because linearIndices is 1 wherever the first value in sortedOutput appears in the original vector.
If you save the result of bsxfun in an intermediate variable:
distances=bsxfun(#minus, z', z)
Then you can look for the values of C in distances using find iteratively.
[rows,cols]=find(C(i)==distances)
This will give all rows and cols if the values are repeated. You just need to then use them for your equation.
You can use accumarray to collect all row and column indices that correspond to the same value in the matrix of differences:
z = [1 3 5 6]; % data vector
zd = bsxfun(#minus, z.', z); % matrix of differences
[C, ~, ind] = unique(zd); % unique values and indices
[rr, cc] = ndgrid(1:numel(z)); % template for row and col indices
f = #(x){x}; % anonymous function to collect row and col indices
row = accumarray(ind, rr(:), [], f); % group row indices according to ind
col = accumarray(ind, cc(:), [], f); % same for col indices
For example, C(6) is value 0, which appears four times in zd, at positions given by row{6} and col{6}:
>> row{6}.'
ans =
3 2 1 4
>> col{6}.'
ans =
3 2 1 4
As you see, the results are not guaranteed to be sorted. If you need to sort them in linear order:
rowcol = cellfun(#(r,c)sortrows([r c]), row, col, 'UniformOutput', false);
so now
>> rowcol{6}
ans =
1 1
2 2
3 3
4 4
I'm not sure I've followed exactly but some points to consider:
unique will sort the data for you by default so you don't need to call sort first
unique actually has three outputs and you can recover your original vector (i.e. with duplicates) using the third output so
[C,~,ic] = unique(reshape(bsxfun(#minus, z', z),1,16))
now you can get back to bsxfun(#minus, z', z),1,16) by calling
reshape(C(ic), numel(z), numel(z))
You might be more interested in the second output of unique which tells you what index each unique value was at in your 1-by-16 vector. It really depends on what you're trying to do though. But with this you could get a list of row column pairs to match your unique values:
[rows, cols] = ndgrid(1:4);
coords = [rows(:), cols(:)];
[C, ia] = unique(reshape(bsxfun(#minus, z', z),1,16));
coords_pairs = coords(ia,:)
which results in
coords_pairs =
1 4
1 3
2 4
2 3
3 4
4 4
4 3
3 2
4 2
3 1
4 1

Matlab: vertical lines at x-values specified by vector

I have a vector of x-values at which I would like to add vertical lines to a graph, say a row vector: vec = [1 2 3 4 5]
I know that you can add single vertical lines like this:
plot([1 1],[0 1])
(gives a vertical line at x=1 from y=0 to y=1).
But when I try something like
vec = [1 2 3 4 5];
lowLine = [0 0 0 0 0];
highLine = [1 1 1 1 1];
plot([vec vec],[lowLine highLine])
It does not give the required result, instead it gives a z-shape. Where am I going wrong?
In order to plot several lines in a single plot, you need to use the fact that MATLAB's plot function handles matrices as inputs, and that it sees each column of the inputs as different plots :
If X and Y are both matrices, then they must have equal size. The plot
function plots columns of Y versus columns of X.
Thus, in order to get the expected result, you need to write :
vec = [1 2 3 4 5];
lowLine = [0 0 0 0 0];
highLine = [1 1 1 1 1];
plot([vec;vec],[lowLine;highLine])
Result :

How to fill the matrix with 0 in matlab [duplicate]

This question already has answers here:
How can I put margins in an image?
(4 answers)
Closed 7 years ago.
Suppose I have a matrix [1 2;3 4], but I need [0 0 0 0;0 1 2 0;0 3 4 0;0 0 0 0], I now how to do it, but is there a function can solve it within one line?
If you have the image processing toolbox, use padarray:
>> A = [1 2; 3 4];
>> B = padarray(A, [1 1])
B =
0 0 0 0
0 1 2 0
0 3 4 0
0 0 0 0
The first input is the matrix you want to pad, and the second input is how many zeroes along the border in each dimension you want to see. You want a 1 element zero border both horizontally and vertically, and so [1 1] is what is required.
However, I'm confused as to why you want this to be in "one-line". If you want a one element border surrounding the original matrix, what's wrong with having multiple lines?
A = [1 2; 3 4];
B = zeros(size(A) + 2);
B(2:end-1,2:end-1) = A;
This is three lines of code, including the definition of your original matrix, but each line is quite clear. You define a new matrix that has 2 more rows and 2 more columns that the original, because you want a 1 element zero boundary around the original matrix, then just place it in the middle.

How to split vector by zeros in MATLAB

I have got a problem with splitting a vector by zeros.
I have a vector for example
v=[1 3 2 6 4 0 0 2 4 6 0 0 0 3 1]
I need to get vectors like
v1=[1 3 2 6 4]
v2=[2 4 6]
v3=[3 1]
Is there any way to do this by using MATLAB functions?
Of course I don't know of how many subvectors are included in main vector v and how many zeros delimits vectors.
I'm not a programmer and also I'm not a pro in MATLAB.
I know a procedural way to do this but want do it by MATLAB somehow.
I found a function A = strsplit(str,delimiter) but I don't have string I have a vector.
So I searched for conversion function. I found S = char(V) but when I executed it it crashed.
It's better to have the output as a cell array, not as separate variables. That way the output will be easier to handle.
Try this:
v = [1 3 2 6 4 0 0 2 4 6 0 0 0 3 1]; %// data
w = [false v~=0 false]; %// "close" v with zeros, and transform to logical
starts = find(w(2:end) & ~w(1:end-1)); %// find starts of runs of non-zeros
ends = find(~w(2:end) & w(1:end-1))-1; %// find ends of runs of non-zeros
result = arrayfun(#(s,e) v(s:e), starts, ends, 'uniformout', false); %// build result
Result (for your example):
>> result{:}
ans =
1 3 2 6 4
ans =
2 4 6
ans =
3 1
The strsplit() solution for a vector of whole numbers smaller than 9 (so a very specific solution, for a general solution see Luis Mendo's). Split and convert back to number:
res = strsplit(char(v), char(0));
res = cellfun(#(x) x - 0,res,'un',0);
celldisp(res)
res{1} =
1 3 2 6 4
res{2} =
2 4 6
res{3} =
3 1

matlab indexing with multiple condition

I can't figure out how to create a vector based on condition on more than one other vectors. I have three vectors and I need values of one vector if values on other vectors comply to condition.
As an example below I would like to choose values from vector a if values on vector b==2 and values on vector c==0 obviously I expect [2 4]
a = [1 2 3 4 5 6 7 8 9 10];
b = [1 2 1 2 1 2 1 2 1 2];
c = [0 0 0 0 0 1 1 1 1 1]
I thought something like:
d = a(b==2) & a(c==0)
but I have d = 1 1 1 1 1 not sure why.
It seems to be basic problem but I can find solution for it.
In your case you can consider using a(b==2 & c==0)
Use ismember to find the matching indices along the rows after concatenating b and c and then index to a.
Code
a(ismember([b;c]',[2 0],'rows'))
Output
ans =
2
4
You may use bsxfun too for the same result -
a(all(bsxfun(#eq,[b;c],[2 0]'),1))
Or you may just tweak your method to get the correct result -
a(b==2 & c==0)