Histogram with a mean line in same spot - matlab

I'm using Matlab and have created a histogram and want a vertical line to indicate the mean. So far my code is
N=100;
mydata=rand(N,1);
mymean=mean(mydata);
histogram(mydata);
figure(1)
hold on
line(mymean,N,'r')
I expect to find a red line crossing the x-axis at the mean value, but there is no line plotted. What is wrong here?

I assume you want your line to go from the point p1=[mymean 0] to the point p2=[mymean N]. Just tell that to the line function. Right now you are drawing a line that only goes to a point, so it is that, a point.
line([mymean mymean],[0 N],'r')
But I see no reason to use line as it is just a low level function of plot, so just do
plot([mymean mymean],[0 N],'r')

Starting in the 2018b version, xline() draws a vertical line.
N = 100;
mydata = rand(N,1);
mymean = mean(mydata);
h = histogram(mydata);
h2 = xline(mymean,'r-','LineWidth',1.5); % Requires MATLAB R2018b or later
Other LineStyles are available: '-', '--', ':', '-.'.
h2.LineStyle = '--';
Color is also easily changed.
For more info, see How to draw horizontal and vertical lines in MATLAB?, especially this answer.

Related

Draw vertical line on histogram plot matlab

Matlab R2015b. I used the following code to draw the histogram:
close all;
hold on;
ko = histograms_windows_1_0{7};
histogram(ko);
set(gca,'XLim',[0 30],'XTick',0:5:30);
xticks = [0;0.16;0.33;0.5;0.66;0.83;1];
set(gca,'XTickLabel', xticks)
xlabel('Seconds');
ylabel('Correct Transitions');
That gives me the picture:
Now I want to add vertical line showing mean value by the "seconds" axis, I already know that value and also the standard deviation. Something similar to:
I have mn and stdv values. I've tried this:
mn = mean(ko) / 30;
stdv = std(ko) / 30;
hax=axes;
line([mn mn],get(hax,'YLim'))
hold off;
But it ignores previously drawn histogram and draws vertical line but only that line is shown, no histogram anymore. How that can be achieved?
The problem is the line
hax=axes;
This creates a new axis object which covers the previous one.
The solution is to change into
hax=gca;
so that the subsequent line goes to the same axis that contains the histogram.

How to draw differently spaced grid lines in Matlab

On mathworks, I have found a code which is suppossed to draw grid lines in a plot:
g_x = -25:1.25:0;
g_y = -35:2.5:-5;
for i = 1:length(g_x)
plot([g_x(i) g_x(i)],[g_y(1) g_y(end)],'k:')% y grid lines
hold on
end
for i=1:length(g_y)
plot([g_x(1) g_x(end)],[g_y(i) g_y(i)],'k:') % x grid lines
hold on
end
here's a link
I don't understand the plot command: e.g. the y grid lines - one of the inputs is a vector containing all the spacing points of the x-axis, where I want to have a grid. These points are given in two columns and they are assigned to the second vector, which only contains the first and the last point shown on the y-axis. As I understand this command, it will for example take the first element g_x(1) and g_y(1) and plot a : , it will then take g_x(2) and g_y(1) and plot :, and so on. But How does it keep on plotting : from g_y(1) continuously until g-y(end) ?
To directly answer your question, it simply plots the two endpoints of each grid line and since the default LineStyle used by plot is a solid line, they will automatically be connected. What that code is doing is creating all permutations of endpoints and plotting those to form the grid.
Rather than creating custom plot objects (if you're using R2015b or later), you can simply use the minor grid lines and modify the locations of the minor tick marks of the axes.
g_x = -25:1.25:0;
g_y = -35:2.5:-5;
ax = axes('xlim', [-25 0], 'ylim', [-35 -5]);
% Turn on the minor grid lines
grid(ax, 'minor')
% Modify the location of the x and y minor tick marks
ax.XAxis.MinorTickValues = g_x;
ax.YAxis.MinorTickValues = g_y;
Basically the code does this:
g_x = -25:1.25:0;
generates a array with values -25.0000 -23.7500 -22.5000 -21.2500 ... 0
These are the positions where vertical lines are drawn
The same holds for g_y, but of course this determines where horizontal lines are drawn.
The option 'k' determined that it is a dashed line.
And the loops just loo through the arrays.
So in the first iteration the plot function draws a line from the position
[-25, -35]
to the position
[-25, -5]
So if you want to change the grid, just change the values stored in g_x
g_x = -25:3.0:0;
would for example draw vertical lines with the width 3.0
I hope this makes sense for you.

How do I plot a horizontal line and a curve in the same graph in MATLAB?

I'm supposed to show the plot of data (curve) and a plot of the average of the data (flat horizontal line) in the same graph. My code computes everything fine and displays the curve in the graph, but I can't get the horizontal line to show up.
plot(1:24,hours3,'b-.',1:24, avg3,'r--');
So the plot of the column "hours3" shows up just fine, but the plot of the average "avg3" does not come up at all. It should be a flat line that extends from points 1 to 24 on the x-axis. Does anyone know why this is?
It's because plot(1:24,avg3,rx--) is interpreted as 24 single points. Using rx-- as linestyle shows you that the points are plotted right but not connected.
plot(1:24,hours3,'b-.',1:24, repmat(avg3,1,24),'r--');
Also with hold on you can keep plotting in an existing figure.
Try below code:
StartPoint=1;
EndPoint=24;
Resolution=1; % you can set 0.1 if you want more precision
Ave=Ave3;% set a value for Ave3
x=[StartPoint:Resolution:EndPoint];
NumberofPoints=((EndPoint-StartPoint)/Resolution)+1;
HrzLine=Ave*ones(1,NumberofPoints);
Curve=0.2*x.^3-4.*x.^2+8;
plot(x,HrzLine);
hold on;
plot(x,Curve);
The 2018b release has made adding horizontal lines (& vertical lines) much easier with yline() (xline() for verticle lines).
Xrng = 1:.01:24;
fh =#(x) 0.2*x.^3 - 4.*x.^2 + 50*sin(x)+ 8; % curve
plot(Xrng,fh(Xrng))
yline(0) % horizontal line at y = 0
Subsequent lines can be added just as easily.
yline(50) % horizontal line at y = 0
xline(12,'b--') % vertical line at x = 12 (blue, dashed)
Requires MATLAB R2018b or later.

Matlab houghlines returns X,Y coordinates out of image boundary

I tested Matlab's Hough transform for detecting lines.
I came up with an odd behavior in the following code:
clc; clearvars; close all;
I = zeros(100,100);
I(50:70,25) = 1;
[H,T,R] = hough(I);
P = houghpeaks(H,1);
lines = houghlines(H,T,R,P,'MinLength',10);
disp([ 'Coordinates for beginning of line (x,y) = '...
,num2str(lines.point1(1,2)),',',num2str(lines.point1(1,1))]);
disp([ 'Coordinates for ending of line (x,y) = '...
,num2str(lines.point2(1,2)),',',num2str(lines.point2(1,1))]);
disp([ 'Length of detected line = ', num2str(norm(lines.point1 - lines.point2)) ]);
One minor quibble is that the original line length is 21 pixels while the houghlines found it to be 18. By setting 'Theta' resolution to a higher precision by substituting
[H,T,R] = hough(I);
to
[H,T,R] = hough(I,'Theta',-90:0.01:89.99);
I reach a value of 20 pixels. Setting values other than 1 to 'RhoResolution' in the Hough transform function messes the results much more.
So this is a bit annoying - the length of the lines is off by 1 (I tested other lengths as well).
What's more bothering is that the original image is 100x100 pixels and if I don't set Theta to a higher resolution, the end points (in my initial example provided here) are off the grid (x coordinate of 108, giving that the terminology here is that the rows are x-axis, the columns are y-axis)!
And if I do set 'Theta',-90:0.01:89.99 the beginning and end points are also completely off from the original points (though they're still within the image boundaries).
Any help on this will be greatly appreciated.
Thank you!

MATLAB fill area between lines

I'm trying to do something similar to what's outlined in this post:
MATLAB, Filling in the area between two sets of data, lines in one figure
but running into a roadblock. I'm trying to shade the area of a graph that represents the mean +/- standard deviation. The variable definitions are a bit complicated but it boils down to this code, and when plotted without shading, I get the screenshot below:
x = linspace(0, 100, 101)';
mean = torqueRnormMean(:,1);
meanPlusSTD = torqueRnormMean(:,1) + torqueRnormStd(:,1);
meanMinusSTD = torqueRnormMean(:,1) - torqueRnormStd(:,1);
plot(x, mean, 'k', 'LineWidth', 2)
plot(x, meanPlusSTD, 'k--')
plot(x, meanMinusSTD, 'k--')
But when I try to implement shading just on the lower half of the graph (between mean and meanMinusSTD) by adding the code below, I get a plot that looks like this:
fill( [x fliplr(x)], [mean fliplr(meanMinusSTD)], 'y', 'LineStyle','--');
It's obviously not shading the correct area of the graph, and new near-horizontal lines are being created close to 0 that are messing with the shading.
Any thoughts? I'm stumped.
You may be getting a problem with using mean as a variable, since it's also a reserved MATLAB command. Try clearing the variable space and then using a unique variable name.
As for the second problem, you want
fill( [x fliplr(x)], [meanUniqueName fliplr(meanMinusSTD)], 'y', 'LineStyle','--');
You also don't need to do this in two steps, but can do it all at once. A code snippet from a script I'm currently working on does the exact same thing and contains the lines:
avar = allan(DATA, tau);
xFill = [avar.tau1 fliplr(avar.tau1)];
yFill = [avar.sig2+avar.sig2err fliplr(avar.sig2-avar.sig2err)];
figure(2);
fill(xFill,yFill,'y','LineStyle','--')
line(avar.tau1,avar.sig2);
So I fill the area between the two error lines, and then draw the data line on top.
It turned out to be a column vs row vector issue. For some reason using the fill method above with flipud with the original column vectors doesn't work, but transposing the original variables then using fliplr does. Go figure. Here's the code in case it helps someone else:
x = linspace(0,100, 101);
mean = torqueRnormMean(:,DOF)';
meanPlusSTD = torqueRnormMean(:,DOF)' + torqueRnormStd(:,DOF)';
meanMinusSTD = torqueRnormMean(:,DOF)' - torqueRnormStd(:,DOF)';
fill( [x fliplr(x)], [meanPlusSTD fliplr(meanMinusSTD)], 'k');
alpha(.25);
plot(x, mean, 'k', 'LineWidth', 2)
plot(x, meanPlusSTD, 'k')
plot(x, meanMinusSTD, 'k')
Note that I removed the dotted line and just used thin vs. thick lines to denote standard deviation and mean. I did this because the line style was inconsistent. This code is in a loop where DOF runs from 1:9, and in some of the subplots both std curves would be dashed and in some just the top or bottom. It didn't matter enough to me to have them dashed so I kept it simple. Now this is an example of the graph I get:
One thing that you appear to be doing wrong is that you're applying fliplr to column vectors. That will have no effect. The example you cited uses row vectors. You also concatenate them into a matrix instead of into a single vector like the example. I think that the equivalent with column vectors would be:
fill( [x;flipud(x)], [mean;flipud(meanMinusSTD)], 'y');
Another possibility:
x = 1:1000; % example x values
y_upper = 5+sin(2*pi/200*x); % example upper curve
y_lower = 2+sin(2*pi/230*x); % example lower curve
bar(x, y_upper, 1, 'b', 'edgecolor', 'b');
hold on
bar(x, y_lower, 1, 'w', 'edgecolor', 'w');
axis([0 1000 0 7])
It uses bar (with unit width and same-color edges) to fill the upper curve, and then a second bar to "remove" (plot in white) the lower part.