How to plot error bars for multiple data points at a single time point
Show older comments
I am new on Matlab and trying to plot error bars on data points. But I have multiple data points at a single time point. Below down is my code:
EXP.t=[0 0 0 0 2.16 3.96 5.83 8.66 13.3 24]; %hours
EXP.Blood_15=[0.05 0.036 0.027 0.021 0.02 0.017 0.015 0.013 0.011 0.008]; %concentration
EXP.errhigh_B15=[0.051 0.044 0.032 0.022 0.021 0.019 0.017 0.012 NaN 0.009]; %concentration
EXP.errlow_B15=[0.048 0.028 0.022 0.02 0.019 0.015 0.012 0.012 NaN 0.007]; %concentration
%plots
figure(1)
%Blood Pharmacokinetics of 15E-03, 183E-03, 1058E-03 mg/g dose GSH-AuNPs
set(gcf, 'Position',[0,45,1800,900])
set(0,'defaultAxesFontName', 'Timesnewroman')
set(0,'defaultTextFontName', 'Timesnewroman')
ylabel(['%ID/g in blood(mg/g)'])%CF of (%ID/g) = mg/g
subtightplot(2,2,1, margins)
bar(EXP.t,EXP.Blood_15)
set(gca,'fontsize',12,'FontName','arial','XScale','lin','Xlim',[0,24],'XTick',[0,6,12,18,24]);
hold on
ylabel(['GSH-AuNPs conc. in blood(mg/g)'])
xlabel(['Time(h)'])
plot(t1,(m_Au_V1+m_Au_A1),'-',EXP.t,EXP.Blood_15,'o','Color', blue,'LineWidth',2)
er = errorbar(EXP.t,EXP.Blood_15,EXP.errlow_B15,EXP.errhigh_B15);
er.Color = [0 0 0];
er.LineStyle = 'none';
lgd= legend('simulated data','experimental data','Location','northeast');
title(lgd,'15E-03 mg/g ID')
hold off
I tried to plot the error bar but shows the error:
Error using bar (line 182)
XData values must be unique.
Error in para_vald_GSH (line 342)
bar(EXP.t,EXP.Blood_15)
So how can I plot error bars for multiple time points at a single time point? Please help me. It will be appreciated. Thank you in advance.
1 Comment
The problem is not with the error bars, but with the bar chart that precedes that plotting.
Let's simplify a little, and look only at the first few points. What is your expectation about what this code's output should look like?
EXP.t=[0 0 0 0 2.16]; %hours
EXP.Blood_15=[0.05 0.036 0.027 0.021 0.02]; %concentration
%plots
bar(EXP.t,EXP.Blood_15)
Because to me, this would create (if MATLAB allowed it) several bars at X = 0, which is difficult to understand/interpret.
Answers (1)
dpb
on 28 Jun 2021
Plot versus ordinal value and then use xticklabels to label the times...
hB=bar(EXP.Blood_15);
hold on
hEr=errorbar(1:numel(EXP.Blood_15),EXP.Blood_15,EXP.errlow_B15,EXP.errhigh_B15,'k','LineStyle','none');
xticklabels(compose('%.2f',EXP.t))
xlabel('Time (hr)')
ylabel('GSH-AuNPs conc. in blood(mg/g)')
yields

Salt to suit; not sure about why the funky-looking y-label text...
If you try to plot() or bar() with actual t values repeated on the axis, then there's nothing to separate the four time zero cases--although I've no idea what this is/represents, those look somewhat peculiar in a decreasing pattern as is -- I presume probably the time isn't actually identically zero but something less than an hour but not recorded, maybe?
14 Comments
Rajvi Amle
on 28 Jun 2021
the cyclist
on 28 Jun 2021
You don't need the bar command at all for that style of plot. You only need the errorbar command. It will make the line, and the errorbars.
- remove the call to bar
- don't use 'LineStyle','none' in the call to errorbar
With the data as presented, the line/errorbar plot is going to be one big blob at t=0; the error magnitudes are as large as the data and will just all mush on top of each other.
OP's data are nothing nearly so clean as the example plots show.
I still can't imagine those points are all identically t=0, though. either, the attached plots look to me like there's a very short time period there, not a perfectly vertical line. But, I could be wrong; I've no klew if there might be somesuch kind of measurement or not but it just doesn't seem likely would get such data if were.
dpb
on 28 Jun 2021
Mimicking one of those with OP's data results in

which looks even more to me as though the actual plots are not all at t==0 but short initial time intervals as compared to the hourly tick marks.
Just for grins, I set
EXP.t(2:4)=[1 2 8]/60;
and it then looks more like the examples albeit still with a lot of noise comparatively.

First without the "fixup" for time was done with
hEr=errorbar(EXP.t,100*EXP.Blood_15,100*EXP.errlow_B15,100*EXP.errhigh_B15,'k-o','MarkerSize',6,'MarkerFaceColor','k');
xlim([-1 25]), ylim([-1 13])
box off
xticks([0:6:24]), yticks([0:4:12])
xlabel('Time (hr)')
ylabel('GSH-AuNPs conc. in blood(mg/g)')
I still don't understand why the 'Tex' interpreter is bolding the NP substring inside the ylabel text -- that seems bizarre behavior.
To produce the second, I just futzed with the XData property aribtrarily...
hEr.XData(2:4)=[1 2 8]/60;
Rajvi Amle
on 28 Jun 2021
Well, you had just posted that you wanted plots that looked like the examples which include lines. Ergo, I drew lines.
But, sure, you can do without--
hEr.LineStyle='none';
will remove it from existing plot or just leave out the "-" linestyle part of the linestyle triplet in the call in the first place.
I'm still curious about the initial data times--it just doesn't make any sense to me these really are all at identically zero times.
Rajvi Amle
on 29 Jun 2021
dpb
on 29 Jun 2021
SUPER!!! And thanks so much for posting back; really nice to know when we're not barking up the wrong tree... :)
Interesting, though, then that you don't actually have a "time zero" value at all.
But, it will certainly make the plots look much nicer and a smoother "decay" or dissolution with time.
Just for grins, you might try
hAx=gca; hAx.XScale='log';
xlim([0.01 25])
xticks([0.01 0.05 0.1 0.5 1 5 10 20
Rajvi Amle
on 30 Jun 2021
Edited: dpb
on 4 Jul 2021
Rajvi Amle
on 4 Jul 2021
dpb
on 4 Jul 2021
Can't run your code but if you have consistent time histories as you describe, then taking mean and std over the population/2D array of those is simply calling mean() and std() with the proper direction -- either default by column if the array is each row a time history or by column (dimension 2) if the time histories are stored by column instead.
As it looks like you know, the error in the mean is std()/sqrt(N) * but you have 10 observations here, not the number in the time history.
Rajvi Amle
on 5 Jul 2021
Well, taking the mean of a vector is trivial; it's not clear what that mean would be representative of in your case if it is one of the time histories.
If you mean a "vector" as the collection of time histories at a given time, then MATLAB will deal with that for you automagically as mean() is vectorized to operate by column by default over a 2D array or, with the optional DIM input argument, it will compute the means of each row (or whatever dimension is given for higher dimensionality arrays).
Example w/ dummy data array--
>> A=rand(4,3); % 4 rows, 3 columns
>> [mean(A); std(A)] % by default operates by column
ans =
0.3914 0.4985 0.3898
0.3439 0.1605 0.4082
>>
So, the above gives the mean and std for each column of the array -- if the time histories are by row for each of the 10 histories and each column is a time step, this is what you want.
>> [mean(A,2), std(A,[],2)] % instead go by row instead of by column
ans =
0.5097 0.3232
0.1475 0.1437
0.4647 0.1904
0.5844 0.3916
>>
If, instead each column represents a time series and the rows are the time steps, then the above computes the statistics again over the collection of time series.
I don't know what more to tell you...
Rajvi Amle
on 7 Jul 2021
Categories
Find more on Chemistry in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!