Plotting Bar graph with logarithmic x axis - matlab

I have a matrix with 2 columns that I would like to display in a bar graph. The y axis should be in intervals of 5 and the x axis in a logarithmic scale of base 10.
As an example I have a matrix [45660 0 ; 3213 5 ; 45631 10 ; 45631 15 ; 300 20]
I found a way to display these points with a logarithmic scale on the x axis, but I would like it to be a bar graph to make it easier to see which 'y' value the points are corresponding to. The width of each bar can be from the x axis value of one point to the x axis value of the next.
PeakCount1=[Load_range Load_count];
semilogx(PeakCount1(:,2),PeakCount1(:,1),'.','MarkerSize',15);
xlabel('Number of Peaks')
ylabel('Load Range (kN)')
title('Number of Peaks Occurring Within Maximum Ice Load Range');
saveas(gcf,'PeakCount_Loadlevels','bmp')

What about using
stem(PeakCount1(:,2),PeakCount1(:,1),'LineWidth',10.0);
set(gca,'XScale','log');
Instead using stem you can use any plot function you like, just insert the second line to make the x axis log.

Related

Equal spacing in bar graph in MATLAB

I have this bar graph in MATLAB, created using the bar command:
I was wondering if there is any way to get rid of empty spaces
between 2478 and 2886, and between 4314 and 5130
If I can get the bars to have an equal amount of space in between them that would be perfect.
As described in the documentation of bar,
bar(x,y) draws the bars at the locations specified by x.
which means that this behavior is intended: Each bar is drawn at the exact position specified by x.
To get equally spaced bars, you can use the categorical function, which converts x to a data type which is intended for discrete categories.
That way, you tell MATLAB that x is not a numerical vector where x(i) is the x-coordinate of the i-th element, but rather a simple label for that value.
bar(categorical(x), y)
Your bars are drawn in the locations of your x data, and are spaced accordingly.
You could plot against [1, 2, 3, ..., 13] and re-label the axes like so
Example data:
x = [1886,2070,2274,2478,2886,3090,3294,3498,3702,3960,4110,4314,5130];
y = rand(1,13)*5 + 32;
Plotting
bar( 1:numel(y), y );
set( gca, 'XTickLabel', x );

Matlab imagesc for data unevenly spaced in y

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)

How to set limits in y-axis in plotting 2-d graph in matlab?

I have x-axis data and y-axis data.
x = [3;4;5;7;11;20;21;23;25;35;50]
y = [90;88;83;81;79;77;76;73;71;71;69]
I want to plot this graph. Now, I need two things:
y-axis should start from 50 and end at 100 with markers at an interval of 5.
On x-axis, I actually want to print 3*3,4*4,5*5, and so on.
How can I do this?
y-axis should start from 50 and end at 100 with markers at an
interval of 5.
http://www.mathworks.com/help/matlab/creating_plots/individual-axis-control.html?searchHighlight=y%20axis%20ticks
on x-axis, i actually want to print 3*3,4*4,5*5, and so on.
x1 = x .* x
then plot x1

Adjusting the x-axis scale on a bar chart in MATLAB

I am trying to adjust the scale of the x-axis so that the values are closer together, but I am not able to do so.
I need the output to be like this photo:
However, what I actually get is the photo below:
Here's the code I have written to reproduce this error:
x = [0.1 1 10 100 1000 10000];
y = [1.9904 19.8120 82.6122 93.0256 98.4086 99.4016];
figure;
bar(x,y);
ylabel('Y values');
xlabel('X values');
set(gca,'XTick', [0.1 1 10 100 1000 10000])
How can I adjust the x-axis so that it looks like the first photo?
Because your data has such huge dynamic range, and because of the linear behaviour of the x axis, your graph is naturally going to appear like that. One compromise that I can suggest is that you transform your x data so that it gets mapped to a smaller scale, then remap your x data so that it falls onto a small exponential scale. After, simply plot the data using this remapped scale, then rename the x ticks so that they have the same values as your x data. To do this, I would take the log10 of your data first, then apply an exponential to this data. In this way, you are scaling the x co-ordinates down to a smaller dynamic range. When you apply the exponential to this smaller range, the x co-ordinates will then spread out in a gradual way where higher values of x will certainly make the value go farther along the x-axis, but not too far away like you saw in your original plot.
As such, try something like this:
x = [0.1 1 10 100 1000 10000]; %// Define data
y = [1.9904 19.8120 82.6122 93.0256 98.4086 99.4016];
xplot = (1.25).^(log10(x)); %// Define modified x values
figure;
bar(xplot,y); %// Plot the bar graph on the modified scale
set(gca,'XTick', xplot); %// Define ticks only where the bars are located
set(gca,'XTickLabel', x); %// Rename these ticks to our actual x data
This is what I get:
Note that you'll have to play around with the base of the exponential, which is 1.25 in what I did, to suit your data. Obviously, the bigger the dynamic range of your x data, the smaller this exponent will have to be in order for your data to be closer to each other.
Edit from your comments
From your comments, you want the bars to be equidistant in between neighbouring bars. As such, you simply have to make the x axis linear in a small range, from... say... 1 to the total number of x values. You'd then apply the same logic where we rename the ticks on the x axis so that they are from the true x values instead. As such, you only have to change one line, which is xplot. The other lines should stay the same. Therefore:
x = [0.1 1 10 100 1000 10000]; %// Define data
y = [1.9904 19.8120 82.6122 93.0256 98.4086 99.4016];
xplot = 1:numel(x); %// Define modified x values
figure;
bar(xplot,y); %// Plot the bar graph on the modified scale
set(gca,'XTick', xplot); %// Define ticks only where the bars are located
set(gca,'XTickLabel', x); %// Rename these ticks to our actual x data
This is what I get:

Horizontal and vertical boxplots in same axes in Matlab

I am trying to plot a set of horizontal and vertical boxplots on the same axes in Matlab R2011b. Using the usual hold on command does not seem to work; only the second set of boxplots is shown. My code is as follows:
bv = boxplot(x,yGrp,'orientation','vertical');
hold on
bh = boxplot(y,xGrp,'orientation','horizontal','position',yPos);
yGrp and xGrp, the grouping index variables are specifically set to be in the range of the y and x datasets, respectively, so that the two plots should naturally have a similar set of values. That is, my x variables spans the range 0-0.05 and my y-variable spans the range 0-1, so yGrp contains a set of categorical numbers between 0 and 1 and xGrp contains bin numbers spanning the range 0-0.05. Similarly, yPos is chosen to span the expected 0-1 range of the vertical axes.
Removing the 'position' argument in the second boxplot call or trying to use simple integer variables does not help. If plotting in separate windows my boxplots look good, but I cannot combine them. What am I doing wrong?
The problem is in axes limits (xlim and ylim). Briefly your 1st boxplots exist but hidden out of axes.
When you plot the second boxplot, it set its own limits ignoring the 1st boxplot. In addition, boxplot by default sets position (y values for horizontal orientation) as 1:number_of_groups, but label them according to your groups. So the ylim will be [0.5 number_of_groups+0.5].
Since your x values are between 0 and 0.05, they are not visible.
As a solution set the limits manually considering this boxplot behavior:
x = rand(10,1)/20;
xg = randi(2,10,1)/40;
y = rand(10,1);
yg = randi(2,10,1)/2;
bv = boxplot(x,xg,'orientation','vertical');
xlim manual
hold on
bh = boxplot(y,yg,'orientation','horizontal');
hold off
xlim([0 2.5])
ylim([0 2.5])
When you set position parameter it determines the values instead of 1:number_of_groups. You can set them close to the range of x.