Is there some way to plot more than 4 line styles in Matlab (as it is stated here https://www.mathworks.com/help/matlab/creating_plots/specify-line-and-marker-appearance-in-plots.html), I mean line styles without markers?
I 've tried https://www.mathworks.com/matlabcentral/fileexchange/1892-dashline but there is some problem, it does not display line correct in the legend.
Next solution for me is gnuplot, but I have whole calculation in Matlab. Is there any other advice, what other to use or what to do with Matlab to make more than 4 line styles? Will there be more line styles in next Matlab version?
There are only 4 line styles, and realistically that's probably a reasonable limit in terms of legibility. But there are lots of marker styles, why not make your own "lines" by plotting close together markers?
x = 1:0.01:2;
a = sin(x);
b = sin(x) - sort(rand(size(x))/4);
c = sin(x) + sort(rand(size(x))/10);
figure;
hold on
plot( x, a, 'linestyle', 'none', 'marker', 's' );
plot( x, b, 'linestyle', '-', 'marker', 'o' );
plot( x, c, 'linestyle', '-', 'marker', '*', 'linewidth', 1, 'markersize', 5);
You might need to do some interpolation to upsample your data to create the line illusion from close-together markers, interp1 is a simple way to do this.
Although I would echo Cris's comment, your plot will quickly become cluttered, consider using subplots, colours, or other devices to illustrate different series and avoid chart clutter.
Related
I have a Matlab script that imports data from a file and creates an exponential fit. I want the script to plot the data points and the fit using the same colour. The legend should be the name of the data file. When I run this same script again for another input file I want the new data and fit to be displayed in the same plot window name of the new data file added to the legend.
What I have so far is this;
expfit = fit(x,y,'exp1')
figure(1)
hold all
plot(x,y,'*','DisplayName','fileName)
legend('Interpreter','none')
legend show
using
plot(expfit,x,y,'DisplayName','fileName')
does not work
How can I add the fitted line to each data using the same colour as the data and
adding the filenames to the legend ?
You're close...
An easy way is to get the colours up front
c = parula(7); % default colour map with 7 colours
figure(1); clf;
hold on
% filename is a variable e.g. filename = 'blah.csv'; from where the data was loaded
plot( x, y, '*', 'DisplayName', filename, 'color', c(1,:) );
plot( expfit, x, y, '-', 'HandleVisibility', 'off', 'color', c(1,:) );
legend('show');
Note by setting HandleVisibility off the fit will not show up in the legend. This is personal preference, I only like one entry for the data and the fit, you could instead use the DisplayName on the 2nd plot too.
Both plots use the same colour using the color input. I've used the first row of the colour map for both, if you plotted some other data you could use the 2nd row etc.
The alternative is to let MATLAB determine the colour automatically and just copy the colour over for the 2nd plot, you need to create a variable (p) of the first plot to get the colour
p = plot( x, y, '*', 'DisplayName', filename );
plot( expfit, x, y, '-', 'HandleVisibility', 'off', 'color', p.Color );
The other code would be the same.
I have this code that I am trying to plot:
battery_aH=55;
hour_of_battery_work=12;
one_battery_price=147.96;
system_amper=1;
while system_amper<20
discharge_battery=1;
[num_of_battery]=num_of_battery1(system_amper,hour_of_battery_work,battery_aH,discharge_battery);
[total_price]=total_price1(one_battery_price,num_of_battery);
plot(total_price,system_amper,'markersize', 30,)
system_amper=system_amper+1;
end
xlabel('price(€)','fontname','times','fontsize',16);
ylabel('Energy of the system[aH]','fontname','times','fontsize',16);
hold off
The thing is that when I run this code I am getting small dots.
Can I change the type of mark through the code (not the size)? Can I draw a line between these dots through the code and after it make the dots disappear?
You can specify any line properties as parameter/value arguments to plot. In your case, you should be able to specify the Marker, MarkerSize, and LineStyle properties
plot(total_price, system_amper, 'Marker', '*', 'MarkerSize', 30, 'LineStyle', '-')
Alternately, you can store the graphics handle to the line object produced by plot and use set to modify the properties
h = plot(total_price, system_amper);
set(h, 'Marker', '*', 'MarkerSize', 30, 'LineStyle', '-')
You are plotting the points one-by-one in the 'while' loop. That's why they are not connected together.
What you want to do is to store all the points in an array and then plot them all at once. Then you can change the line and mark specs using plot options.
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.
In MATLAB, I plot many different vectors to a figure. Now, what I would like to do is simply undo the last vector that I plotted to that figure, without clearing everything else. How can this be accomplished? Can it be accomplished?
Thanks
Edit:
figure(1); clf(1);
N = 100;
x = randn(1,N);
y = randn(1,N);
z = sin(1:N);
plot(x); hold on;
plot(y,'r');
plot(z,'k');
Now here, I would like to remove the plot z, which was the last plot I made.
If you know before plotting that you want to remove it again later, you can save the handle returned by plot and delete it afterwards.
figure;
h1 = plot([0 1 2], [3 4 5]);
delete(h1);
Try
items = get(gca, 'Children');
delete(items(end));
(or maybe delete(items(1)))
The answer that #groovingandi gives is the best way to generally do it. You can also use FINDALL to find the handle based on the properties of the object:
h = findall(gca, 'type', 'line', 'color', 'k');
delete(h);
This searches the current axes for all line objects (plot produces line objects) that are colored black.
To do this on, say, figure 9, you need to find the axes for figure 9. Figure handles are simply the figure number, so:
ax = findall(9, 'axes');
h = findall(ax, 'type', 'line', 'color', 'k');
delete(h);
I plot many lines on top of one another, using plot and hold on
however i want one of the lines to be shifted a bit if it falls on another line.
for example in the following case:
plot(1:100); hold on; plot(-100:100,abs(-100:100))
i want it to be clear that there are 2 plots here
i tried to simply increase x values for different plots but this skews the data too much
for z=1:numberofplots
plot((1:size(locations,2))+0.1*z,locations(z,:)','color', altclrz(z,:));
end
You can differentiate the curves in several ways:
-1- Skewing the data
As you said, you could shift the data a bit. I would suggest fixing your axis and then calculating how many units in linewidth is so you get a very tight fit, like this:
lineWidth = 5;
figure(33);
clf;
subplot(1,2,1);
h = plot(myData, 'linewidth', lineWidth);
xlim([1,5]);
ylim([1,5]);
title('Original');
myData = meshgrid(1:5)';
myLimDiff = diff(ylim);
set(gca,'units', 'pixels');
myPos = get(gca, 'position')
myWidthHeight= myPos(3:4)
PixelsPerUnit =myWidthHeight(2)./ myLimDiff;
myDataSkewed = myData + meshgrid(-2:2)*1/PixelsPerUnit(1)*lineWidth;
subplot(1,2,2);
plot(myDataSkewed, 'linewidth', lineWidth);
xlim([1,5]);
ylim([1,5]);
title('Skewed');
Result:
-2- Using solid lines and Dashes
As someone else noted in the comments, you could you a dashed line over a solid line, or some combination of styles.
-3- Using different line thickness
Use different line widths with the thickest on the bottom:
figure(54);
clf
hold all
for ind = 10:-3:1
plot(1:5, 'linewidth', ind);
end
-4- Use separate plots for each line with a twist
Another way to call out each line is to plot each line in a subplot but to plot all the data in gray first. This way you can see where all the lines are with each particular line called out:
figure(55);
clf
data = rand(3);
for ind = 1:3
subplot(1,3,ind);
plot(data, 'linewidth', 4, 'color', [1 1 1]*.75);
hold on
plot(data(:,ind), 'linewidth', 2);
end