I have a number vector, let's say v=[1 1 1 1000 20 20]; I want to build very simple histogram-like plot where y-axis will be counts ( 3,1,2 in this case), but the x-axis will be 1,20,1000 equally spaced. Meaning that Matlab will ignore the fact that 1000>>20 and space them as it will 1,2,3 in the plot.
I will show that I mean. I can do it by:
x=[1 1 1 1000 20 20];
histogram('Categories',{'1','20','1000'},'BinCounts',[numel(find(x==1)), numel(find(x==20)), numel(find(x==1000))])
But it's kind of clumsy and gawky way. I have to know the categories beforehand. Can it be done in more elegant way?
first convert X to categorical matrix
convert to categorical
then histogramplot X with these categories:
plot categorial histogram
in case of your problem:
C = categorical(x,[1 20 1000],{'1','20','1000'})
//or just C=categorical(x,[1 20 1000]) or simply C=categorical(x)
histogram(C)
Related
Is it possible in imagesc to specify the x-axis a column vector such that the ticks and data points(pixels) are placed on the corresponding points? As far as I understood from the manual you only specify the corners of the image and this is not a problem as long as your data is evenly spaced like 100:100:1000.
In my case the x-axis consists of 21 elements which are evenly spaced like 1200:50:1700, whereas the y-axis is the vertical concatenation of two evenly spaced column vectors 200:50:450 and 500:25:725. My aim is to have the data points(pixels) at the correct locations, but it seems impossible to do so. Is there a workaround?
One option is to make Y also evenly spaced, and than use repelem:
X = 1200:50:1700;
Y = [0 50 100 200:50:450 500:25:725 800];
% set the spacing factor:
spacing = round(diff(Y)/min(diff(Y)));
The spacing vector looks like:
spacing =
Columns 1 through 14
2 2 4 2 2 2 2 2 2 1 1 1 1 1
Columns 15 through 19
1 1 1 1 3
and defines the distance between elements as multiplications of the smallest distance between elements in the vector.
We then define our new 'Y' for the image, so it will be evenly spaced, with the smallest space between elements in the vector.
% Define the new Y:
Y_spaced = Y(1):min(diff(Y)):Y(end); % = 0:25:800
% some arbitrary data:
data = rand(numel(Y),numel(X));
We use the spacing vector as input for repelem to duplicate each row in data as much as needed:
% spacing the data:
data_spaced = repelem(data,spacing([1 1:end]),1,1);
And we can plot it using imagesc (either in the matrix ij orientation, or in cartesian xy orientation):
imagesc(X,Y_spaced,data_spaced)
axis xy
The result:
Try replace imagesc with surf command:
surf(1200:50:1700, [200:50:450 500:25:725], rand(16,11), 'EdgeColor','none');
view([0 90]);
Note: with this way you loose last column and last row compare to imagesc, but you can just duplicated these data before displaying.
Use contourf or interpolate the data to a grid that fits all data points using e.g. interp2 or plot using contourf
Initialize data
X=[1200:50:1700]
Y=[200:50:450 500:25:725]
V = peaks(max(size(X,2),size(Y,2)))(1:size(Y,2),1:size(X,2));
Plot using contourf
contourf(X,Y,V);
view([0 -90]);
Interpolate and plot
Xq=linspace(min(X),max(X),100);
Yq=linspace(min(Y),max(Y),100)';
Vq = interp2(X,Y,V,Xq,Yq,'nearest');
imagesc(Vq)
If you want to have your pixels exactly at the correct location, you need to use a grid that has points exactly at all the point of your Y vector of course, so you need to adjust the "100"s accordingly to your screen and data resolution.
The alternative is to use pcolor
pcolor(X,Y,V)
view([0 -90]);
(Be careful with all the up-down flipping between image data and real data)
Let
input = [0 0 0 5 5 7 8 8];
I now want to transform this vector into the form
output = [3 3 3 3 5 5 6 8];
Which basically is a stairs plot.
Explanation
The input vector is used to plot data points along the x-axis. The y-axis is thereby provided by 1:length(input). So the resulting plot shows the cumulative number of datapoints along the y-axis and the time of occurrence along the x-axis.
I now want to fit a model against my dataset. Therefor I need a vector that provides the correct value for a certain time (x-value).
The desired output vector basically is the result of a stairs plot. I am looking for an efficient way to generate the desired vector in matlab. The result of
[x, y] = stairs(input, 1:length(input));
did not bring me any closer.
It can be done with bsfxun as follows:
x = [0 0 0 5 5 7 8 8];
y = sum(bsxfun(#le, x(:), min(x):max(x)), 1);
This counts, for each element in 1:numel(x), how many elements of x are less than or equal to that.
I have two vectors of the same size. The first one can have any different numbers with any order, the second one is decreasing (but can have the same elements) and consists of only positive integers. For example:
a = [7 8 13 6];
b = [5 2 2 1];
I would like to plot them in the following way: on the x axis I have points from a vector and on the y axis I have the sum of elements from vector b before this points divided by the sum(b). Therefore I will have points:
(7; 0.5) - 0.5 = 5/(5+2+2+1)
(8; 0.7) - 0.7 = (5+2)/(5+2+2+1)
(13; 0.9) ...
(6; 1) ...
I assume that this explanation might not help, so I included the image
Because this looks to me as a cumulative distribution function, I tried to find luck with cdfplot but with no success.
I have another option is to draw the image by plotting each line segment separately, but I hope that there is a better way of doing this.
I find the values on the x axis a little confusing. Leaving that aside for the moment, I think this does what you want:
b = [5 2 2 1];
stairs(cumsum(b)/sum(b));
set(gca,'Ylim',[0 1])
And if you really need those values on the x axis, simply rename the ticks of that axis:
a = [7 8 13 6];
set(gca,'xtick',1:length(b),'xticklabel',a)
Also grid on will add grid to the plot
How can I use the plot function to mark the peak?
Example:
a = [0 1 3 23 3 9 10 28 2]
[p,locs] = findpeaks(a)
Result:
p =
23 28
locs =
4 8
You dont provide an x range so create one (you can change this to what you want).
figure
x = [1:length(a)];
plot(x,a,'k');
The above plots your original data points the following will
hold on
plot(locs,p,'ro');
plot your peaks as red circle points on top of the original series. If you need a non-integer x-range you will need to calculate the appropriate values that correspond to the indices in your locs array and use those x values instead.
I am new to this forum, so please bear with me.
I have been working on this Matlab problem for a while now:
I have a digital elevation model (DEM) new_sub(x,y) in tif format. So it is a x-by-y matrix containing heights (z). I wish to resample parts of this DEM in different resolutions and restore this in another matrix. So far I have been working with for loops to change the resolution of different areas of the DEM and then wrote the results to an xyz-file:
x y z
1 1 123
1 2 233
1 3 231
2 1 235
2 2 531
2 3 452
and so forth.
Here is the code:
xmax = size(new_sub,2);
ymax = size(new_sub,1);
for k=1:200 % y
for l=1:xmax % x
fprintf(fid, '%d %d %d \n',l,xmax+1-k,new_sub(k,l));
end
end
% 1:4
for k=200/2+1:size(new_sub,1)/2
for l=1:size(new_sub,2)/2
fprintf(fid, '%d %d %d \n',l*2,ymax+2-k*2,new_sub(k*2,l*2));
end
end
This does work, but seems to be rather complicated. Moreover, it does not allow me to store the resampled areas in a single matrix within Matlab.
Is there a more efficient way of resampling certain areas of a Matrix with different resolutions, writing them into a new Matrix containg all resampled areas and then writing it to a file? I was looking into repmap, but could not think of a clever way of using it!
Your help is much appreciated!
THeo
To re-sample a matrix in Matlab:
For example matrix M:
M = [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];
If we wanted to sample on every nth pixel, it is as simple as this:
m = M(1:n:end, 1:n:end)
So for n=2
m = 1 3 5
11 13 15
21 23 25
I suggest you read up on indexing in matlab and also on using the colon operator to create vectors in matlab
Now in order to get in the "x y z" format you mentioned, first use meshgrid to generate matrices of X and Y coordinates.
[X, Y] = meshgrid(1:n:size(M,1), 1:n:size(M,2))
notice I use n to downsample X and Y. Now you just need to flatten the three matrices and combine them:
final = [X(:), Y(:), m(:)]
Finally to save as a file I suggest you type help save or help dlmwrite in the Matlab command promt and use either of those functions to save final
To me the easiest way to do looks like using imresize. You can treat your elevation map as an image I. Then you can cut sections out by indexing and rescaling as follows:
I = imread('my.tiff'); % read
section = I(1:200, :); % cut the first 200 rows and all columns
sectionResized = imresize(section, [numrows numcols]) % resample
imwrite(sectionResized, 'mynew.tiff'); % save