How to calculate average function with multiple functions

I'm trying to create an average battery discharge line as a function of SOC with multiple data sets.
The discharge data plotted in the file 'ICR1865022P_Testdata.mat' will give the figure above. Now what I want is to calculate an average discharge curve that will be used for further calculations of the battery discharge Voc.
I'm attaching the measurement data and an .m file to properly display the problem. In the .m file provided I've taken the discharge curve of 'LoadV_discharge5' as an example but the plan is to use the calculated average from there on. I think the bump in the road, for me, is the different lengths of the data sets. This is preventing me of calculating an average out of the data sets. In my mind the only way to create an average functions is to calculate functions out of every data set and then calculate an average function out of those functions.. Its kinda difficult to explain so if I'm leaving any info out, please let me know!
Kind regards,
Michel.

 Accepted Answer

I’m not certain what plot I’m looking at in your Question. I could not figure out how to reproduce it in my code, so I will let you plot it.
I did manage to interpolate and then take the means and standard deviations what I believe to be the variables you are interested in. If they are not, my code should at least provide a way for you to do the interpolations and other calculations on the correct variables. I used the longest ‘t_discharge’ vector as the basis of the interpolation, so the ‘LoadV_discharge’ vectors (matrix) are all interpolated to the same times, that being ‘t_discharge{Idx}’.
The code:
load('Michel de Jongh ICR1865022P_Testdata.mat'); % Load Data Into Workspace
vars_t_d = whos('t_discharge*'); % Get ‘t_discharge’ Names
vars_LV_d = whos('LoadV_discharge*'); % Get ‘LoadV_discharge’ Names
for k1 = 1:length(vars_t_d)
t_discharge{k1} = eval(vars_t_d(k1).name); % Create ‘t_discharge’ Cell Array
LoadV_discharge{k1} = eval(vars_LV_d(k1).name); % Create ‘LoadV_discharge’ Cell Array
vctlen(k1) = length(t_discharge{k1}); % Vector Lengths
end
[LenMax,Idx] = max(vctlen); % Longest Vector & Index
for k1 = 1:length(vars_t_d) % Interpolation Loop
LoadV_disch_intrp(:,k1) = interp1(t_discharge{k1}, LoadV_discharge{k1}, t_discharge{Idx}, 'spline', 'extrap');
end
figure(1)
plot(t_discharge{Idx}/3600, LoadV_disch_intrp)
grid
LoadV_disch_mean = mean(LoadV_disch_intrp, 2); % Column Vectors, So Take Means Across Rows
LoadV_disch_std = std(LoadV_disch_intrp, [], 2); % Column Vectors, So Take Standard Deviations Across Rows
figure(2)
plot(t_discharge{Idx}/3600, LoadV_disch_mean, '-r')
hold on
plot(t_discharge{Idx}/3600, LoadV_disch_mean+1.96*LoadV_disch_std, '-g')
plot(t_discharge{Idx}/3600, LoadV_disch_mean-1.96*LoadV_disch_std, '-g')
hold off
grid
I apologise for the delay. I was doing my best to reproduce your plot to check my calculations, and cannot figure out what you are plotting. (I used your code as a basis for mine, but did not run it.) The benefit of my code is also that it creates a matrix of your dynamically-named variables and then does all the calculations on the matrix. You might also find a 'linear' interpolation to be preferable to 'spline'.
I would retain the 'extrap' option in the interp1 call regardless. (It requires that you specify a method.) It will avoid errors if your ‘t_discharge’ variables do not all begin and end at the same times.

5 Comments

I'm sorry I didn't specify the figure on the question. The figure can be plotted with the following code:
load('ICR1865022P_Testdata.mat');
figure
plot ([100:-(100/(length(LoadV_discharge02)-1)):0], LoadV_discharge02, ...
[100:-(100/(length(LoadV_discharge05)-1)):0], LoadV_discharge05, ...
[100:-(100/(length(LoadV_discharge1)-1)):0], LoadV_discharge1, ...
[100:-(100/(length(LoadV_discharge2)-1)):0], LoadV_discharge2, ...
[100:-(100/(length(LoadV_discharge3)-1)):0], LoadV_discharge3, ...
[100:-(100/(length(LoadV_discharge5)-1)):0], LoadV_discharge5, ...
[100:-(100/(length(LoadV_discharge7)-1)):0], LoadV_discharge7, ...
[100:-(100/(length(LoadV_discharge10)-1)):0], LoadV_discharge10);
title ('Discharge and State of Charge - ICR1865022P');
xlabel ('State of Charge');
ylabel ('Voc');
legend ('0.2A - Discharge rate', '0.5A - Discharge rate', '1A - Discharge rate', '2A - Discharge rate', ...
'3A - Discharge rate', '5A - Discharge rate', '7A - Discharge rate', '10A - Discharge rate','Location','northoutside','Orientation','horizontal');
grid on
''[100:-(100/(length(LoadV_discharge#)-1)):0]'' is essentialy the State of Charge (100% is full {highest LoadV_discharge#}, 0% is empty {lowest LoadV_discharge#}). The voltage of the battery is highest at a State of Charge of 100% and starts to decrease with a decreasing State of Charge. This is the x axes. So the above figure is only generated with the ''LoadV_discharge#'' data (# = 02, 05, 1, 2, 3, 5, 7, 10) and the x axes is just a product of the length of each individual ''LoadV_discharge#'' data divided in 100% to 0%.
I'm trying to figure out the code you send ( thanks alot to start with!) but I'm not sure what you did there. I THINK you calculated the average 't_discharge' but what I need to achieve is to calculate the average 'line' of the figure I posted in the question (and the code above I'm sending). Each line is a different dataset (which consists of LoadV_discharge# and the length of LoadV_discharge# which is divided in 100% down to 0%). It is like physically drawing an 'average' line between the different 'Discharge rates' as explained in the legend of the figure. I did a windows paint in the figure below in black to visualize the data set that I need to calculate (Looks away in shame).
I'm going to try and wrestle with the code you send me but some of the thing you did there are completly new to me so bear with me hehe. Again, thanks for your help!
I didn’t calculate the average ‘t_discharge’. I created an interpolated ‘LoadV_discharge’ matrix and then calculated the average ‘LoadV_disch_mean’ and ‘LoadV_disch_std’ from it.
Now that I sort of understand what you’re doing and what you want, this revised code seems to work:
load('Michel de Jongh ICR1865022P_Testdata.mat'); % Load Data Into Workspace
vars_t_d = whos('t_discharge*'); % Get ‘t_discharge’ Names
vars_LV_d = whos('LoadV_discharge*'); % Get ‘LoadV_discharge’ Names
for k1 = 1:length(vars_t_d)
t_discharge{k1} = eval(vars_t_d(k1).name); % Create ‘t_discharge’ Cell Array
LoadV_discharge{k1} = eval(vars_LV_d(k1).name); % Create ‘LoadV_discharge’ Cell Array
vctlen(k1) = length(t_discharge{k1}); % Vector Lengths
end
[LenMax,Idx] = max(vctlen); % Longest Vector & Index
for k1 = 1:length(vars_t_d) % Interpolation Loop
LoadV_disch_intrp(:,k1) = interp1([100:-(100/(size(LoadV_discharge{k1},1)-1)):0], LoadV_discharge{k1}, [100:-(100/(size(LoadV_discharge{Idx},1)-1)):0], 'spline', 'extrap');
end
figure(1)
plot(t_discharge{Idx}/3600, LoadV_disch_intrp)
grid
xlabel('t\_discharge')
ylabel('Interpolated LoadV\_discharge Vectors')
LoadV_disch_mean = mean(LoadV_disch_intrp, 2); % Column Vectors, So Take Means Across Rows
LoadV_disch_std = std(LoadV_disch_intrp, [], 2); % Column Vectors, So Take Standard Deviations Across Rows
figure(2)
plot(t_discharge{Idx}/3600, LoadV_disch_mean, '-r')
hold on
plot(t_discharge{Idx}/3600, LoadV_disch_mean+1.96*LoadV_disch_std, '-g')
plot(t_discharge{Idx}/3600, LoadV_disch_mean-1.96*LoadV_disch_std, '-g')
hold off
grid
legend('\mu Interpolated LoadV\_discharge', '±1.96\cdot\sigma Interpolated LoadV\_discharge', 'Location','NE')
xlabel('t\_discharge')
ylabel('Interpolated LoadV\_discharge Vectors')
figure(3)
plot([100:-(100/(size(LoadV_disch_intrp(:,1),1)-1)):0], LoadV_disch_mean, '-r')
hold on
plot([100:-(100/(size(LoadV_disch_intrp(:,1),1)-1)):0], LoadV_disch_mean+1.96*LoadV_disch_std, '-g')
plot([100:-(100/(size(LoadV_disch_intrp(:,1),1)-1)):0], LoadV_disch_mean-1.96*LoadV_disch_std, '-g')
hold off
grid
legend('\mu Interpolated LoadV\_discharge', '±1.96\cdot\sigma Interpolated LoadV\_discharge', 'Location','NW')
xlabel('Charge (%) ?')
ylabel('Interpolated LoadV\_discharge')
My original code was essentially correct. I re-coded the interpolation loop using the x-values you used in the plot to do them, rather than the time. I then plotted the interpolated values. The mean and standard deviations calculate and plot correctly. I used the normal distribution for the confidence limits, although the t-distribution is actually appropriate here, since there are only 8 observations (with 7 degrees-of-freedom).
This code is perfect. I kinda see what you did in your first code and you were right, that one was indeed correct. I just didn't see the logic/math behind it.
Thank you so much for your explanation this is very helpful and I'm learning alot from this!
Thank you. My pleasure!
I enjoy helping with research data analysis problems because I feel I’m actually doing something. Yours was one of the most complicated and challenging I’ve ever encountered! I’m learning a lot as well.
One item I thought of is to create a vector from your independent variable to make the code a bit easier to read:
PctCharge = [100:-(100/(size(LoadV_disch_intrp(:,1),1)-1)):0];
The interpolated variable length is the same for all the interpolated vectors, so one size now fits all. Rename it to represent what it actually is — I called it ‘percent charge’ because I don’t know what it is.
Hi there,
I came across this old thread which luckily addresses exactly what I am struggling with. The only issue is that I was hoping to inspect Michel's .mat file to see how exactly he organized his data. I know how to load the file into my script but not sure how to actually open the file and look at the content.
Thanks in advanced!

Sign in to comment.

More Answers (0)

Categories

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!