How to loop a function though multiple datasets
Show older comments
Hello everyone,
I have a bit of a basic question, and I've tried reading other answers on this, but they each seem to have their own specific problem (nor have I been able to successfully implement their solutions to my own issues).
In a nutshell, I have successfully been able to use lsqccurvefit for one of my datasets. I am now trying to create a loop, so I can run the same function on multiple datasets. My code is this:
Data1=[0.596421471 0.06
0.5859375 0.119284294
0.566037736 0.29296875
0.530035336 0.622641509
0.418994413 1.219081272
0.388619855 3.058659218
];
Data2=[5.00E+04 3.82E+04 3.45E+04 3.42E+04 3.74E+04 3.21E+04 2.81E+04 2.88E+04
5.00E+04 3.82E+04 3.45E+04 3.42E+04 3.74E+04 3.21E+04 2.81E+04 2.88E+04
3.08E+04 3.07E+04 2.19E+04 2.23E+04 2.53E+04 2.05E+04 1.98E+04 1.89E+04
2.05E+04 1.87E+04 1.30E+04 1.10E+04 1.62E+04 1.31E+04 1.05E+04 1.05E+04
8963 1.11E+04 6243 3504 6454 4346 4448 4357
0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00
];
Pt=Data1(:,1);
Lt=Data1(:,2);
Int=Data2(:,1);
plot(Lt,Int, 'ro');
xdata=[Pt,Lt]
F=@(x,xdata)((xdata(:,1)+xdata(:,2)+x(2))-((xdata(:,1)+xdata(:,2)+x(2)).^2-4.*xdata(:,1).*xdata(:,2).^1/2).*x(1)/2.*xdata(:,1))
x0=[1 1]
options=optimoptions('lsqcurvefit','MaxFunEvals',5e2)
lb=-Inf
up=+Inf
[x,resnorm,~,exitflag,output]=lsqcurvefit(F,x0,xdata,Int,lb,up,options)
hold on
plot (Lt, F(x,xdata))
hold off
Data 1 is constant and does not change, it is what my function is using. Data2 is my data. I am also plotting my data and the output of the function so I can see how well they match (which has so far been extremely poor matching). What I want to do now is have my [Int] cycle through each column independently, so for the first round it runs the lsqc through column ;1, 2nd round through column ;2, etc. At the same time, I would also like to individuallly (or combined) plot each individual column with the output of the function (for each run it goes through). I know I need to use the "for" function, but I don't quite know how to cycle through each column individually using the Int that I've already defined.
Finally, I had gotten this to work using one column set, but now that I've inputed multiple column sets, I seem to have broken my script. I now get the error
Index in position 1 is invalid. Array indices must be positive integers or logical
values.
Error in Testscript4loop (line 18)
plot(Lt,Int, 'ro');
Which is strange, since before I added all the extra data (Data2 used to be only 1 column), it worked fine.
10 Comments
Adam
on 11 Mar 2019
for n = 1:size( Data2 )
Int=Data2(:,n);
...
end
should work, depending how many plots you want at once and what results you may want to store for outside the loop (just put these into an array indexed by n).
The error you report doesn't seem to be in any way related though and looks like the kind of error you would get if you have declared a variable named plot which is hiding the function of the same name (never do this!).
Sam Mahdi
on 11 Mar 2019
Actually
1:size( Data2 )
was a typo and should read
1:size( Data2, 2 )
so I'm slightly surprised that works as it was!
Putting this in a loop will tell it to run the loop as many times as there are columns in Data2.
doc for
should help you understand for loops.
Int=Data2(:,n);
will take the nth column of Data2 and because it is in a loop defined as above n will increment from 1 up to the number of columns of Data2 each time round the loop.
Putting results in an array indexed by n depends on whether you want to keep the results from a loop outside of the loop (if not they will be overwritten next time round the loop). If you don't then your plot instruction can stay the same (though you will need a hold on instruction to ensure next time round the loop your plot is added). If you do want to keep the results then e.g.
Int(:,n) = Data2(:,n)
will do this. Though you should predefine Int as:
Int = zeros( size( Data2 ) );
In the case of Int this is pointless though as you would just end up with a copy of Data2, but later results can be stored in this way.
I don't know anything about lsqcurvefit though so I can't help with improving its results.
Sam Mahdi
on 12 Mar 2019
doc size
tells you about the arguments to the size function and what it returns. The documentation, combined with the command line is by far your best resource for understanding how functions work. Get used to using both and it will help your learning immeasurably. I've been using Matlab for 13 years now, but I still always have multiple tabs open in the help as I am always referring to something or other and am constantly trying things out on the command line with test matrices or whatever other inputs I need. For example:
>> a = rand( 3, 4 );
>> size( a )
ans =
3 4
>> size( a, 1 )
ans =
3
>> size( a, 2 )
ans =
4
Very simple to test in under a minute and helps you understand what results are giving.
Specifically, here if you don't give a second argument to the size function you get an array of results, giving the size for each dimension (rows first, then columns). Passing '2' in says 'give me the size of dimension 2 - i.e. columns'.
I've never really worked out what a for loop or if statement does if you give it something unexpected like a vector when it wants a scalar - I just make sure not to do it!
But in this case again you can test very quickly and see :
>> 1:size( a )
ans =
1 2 3
which is to be expected really. It just takes the first output of the size function (the number of rows), so unless you happen to have the same number of rows as columns then your for loop would either crash or miss some data out doing this while indexing columns.
As for your plotting, I can't work out, just at a glance, (and especially not seeing the updated code with the loop), what the sizes are of x and xdata when you plot them, but again, a breakpoint on the relevant line and
size( x )
size( xdata )
on command line will soon tell you this. They need to both be vectors, of equal length, in order to plot.
Sam Mahdi
on 12 Mar 2019
Adam
on 13 Mar 2019
Again I've lost track of exactly what dimensionality various results are, but the mean function also has an (optional) dimension argument to tell it which dimension to calculate the mean over. It may be that you are doing it long the wrong dimension and may need
M = mean( x, 2 )
instead.
Sam Mahdi
on 13 Mar 2019
Adam
on 13 Mar 2019
So you will need to store whatever data is relevant in the loop in an array instead of plotting it. As it stands you will end up with a mean value per column of your data, each of which gets thrown away apart from the one for the final column.
Answers (0)
Categories
Find more on Loops and Conditional Statements 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!