I have several large data sets which follow the following pattern: A position is measured, a force is applied until a new equilibrium is found.
I'd like to find a fit for the position, at least at the plateaus, and preferably of the inter lying section, which in this case approaches a line.
I tried fitting the data with Clip
, and with Piecewise
.
nlm = NonlinearModelFit[v40s1000h,Piecewise[{{a, x < A}, {b, x > B}}], {a, b, A, B, c, d}, x]
This creates a decent fit only if I specify the values for A and B, but then I have to estimate those values for each data set manually. It also doesn't really work to just add NMinimize
, or add the piecewise part for the middle bit.
Is There anything else I can try?
http://s000.tinyupload.com/?file_id=35616536027018518052 << file
Answer
As usual, it's a matter of choosing a better starting values for the parameters.
I started writing this answer before the data file was uploaded, so here's some synthetic data:
data = Table[
Interpolation[{{0, 1.1*^-6}, {200, 1.1*^-6}, {250, 9.5*^-7}, {500,
9.5*^-7}}, x, InterpolationOrder -> 1] +
2*^-8 RandomVariate[NormalDistribution[]], {x, 0, 500}];
ListPlot[data]
As @nikie suggested in the comments, you should define your model to return something in the intermediate values. I'll use a linear transition because that seems to match your data.
f[x_] := Piecewise[{{a, x < xa}, {a + (b - a) (x - xa)/(xb - xa), xa <= x < xb}, {b, xb <= x}}]
Now we do the fit:
fit = NonlinearModelFit[data, f[x], {a, b, xa, xb}, x];
fit // Normal // InputForm
(* Piecewise[{{1., x < 1.}, {1.016964195743597*^-6, 1. <= x}}, 0] *)
No good. Why? The documentation for NonlinearModelFit
says "give starting values when parameters are far from the default value 1". Let's try that.
fit = NonlinearModelFit[data, f[x], {a, b, {xa, 100}, {xb, 200}}, x];
fit // Normal // InputForm
(* Piecewise[{{1.1004729741760495*^-6, x < 200.73035367387615},
{1.1004729741760495*^-6 - 2.914483888454594*^-9*(-200.73035367387615 + x),
200.73035367387615 <= x < 253.00000699926912},
{9.481339117040847*^-7, 253.00000699926912 <= x}}, 0] *)
That's better.
Show[ListPlot[data], Plot[fit[x], {x, 0, 500}, PlotStyle -> {Red, Thick}]]
Comments
Post a Comment