# Find a best fitting curve for some data with no regular pattern

Suppose some data with no regular pattern is given, so common patterns of functions all fail to fit it. Then how can one find the best fitting curve? I believe there will be some data for which we can not find any regular pattern. One can try with the following data (luckily, we know that this sequence has a limit):

  {{1, 0.08888888888888872},{2, 0.13842641081508972},{3, 0.17153280014540232},
{4, 0.19586894934728782},{5, 0.21482500502852542},{6, 0.23017213935351592},
{7, 0.24294479920054762},{8, 0.25379708095478332},{9, 0.26316771779066082},
{10, 0.27136463872018062},{11, 0.27861184976714762},{12, 0.28507709754351612},
{13, 0.29088903838678592},{14, 0.29614834727916052},{15, 0.30093516063430942},
{16, 0.30531421254734282},{17, 0.30933847047870212},{18, 0.31305176609215322},
{19, 0.3164907360488469}}


Any help or suggestion will be appreciated!

• This reply of mine fits inerpolation functions to data. No equation is used. – Hugh Jul 17 '15 at 20:03

May be something here of use: https://mathematica.stackexchange.com/a/14232/363

data=
{{1, 0.08888888888888872},{2, 0.13842641081508972},{3, 0.17153280014540232},
{4, 0.19586894934728782},{5, 0.21482500502852542},{6, 0.23017213935351592},
{7, 0.24294479920054762},{8, 0.25379708095478332},{9, 0.26316771779066082},
{10, 0.27136463872018062},{11, 0.27861184976714762},{12, 0.28507709754351612},
{13, 0.29088903838678592},{14, 0.29614834727916052},{15, 0.30093516063430942},
{16, 0.30531421254734282},{17, 0.30933847047870212},{18, 0.31305176609215322},
{19, 0.3164907360488469}};

nlm = NonlinearModelFit[data, {a + b Log[c x], c > 0}, {a, b, c}, x];
Print@Normal@nlm;
Print@FindFit[data, {a + b Log[c x], c > 0}, {a, b, c}, x];
Show[Plot[nlm[x], {x, 1, Length@data}, PlotRange -> All],
ListPlot[data, PlotStyle -> Directive[Red, PointSize[0.02]]]]


See also, http://reference.wolfram.com/mathematica/tutorial/CurveFitting.html - particularly the section: 'Searching for general fits to data'.

• Thanks very much! As the example in the question, I can give more data and the sequence has a limit. But in more general case waht if we can not find a common pattern of function to fit the data very well? – Eden Harder Aug 15 '13 at 10:12
• I've added a link to the curve fitting tutorial. There are only a few general cases to try before one may need to resort to a polynomial fit. – Chris Degnen Aug 15 '13 at 10:19
• Thanks a lot! As the example in the question, I have try some possible cases. Since the sequence will converge, a polynomial fit will not help after all. – Eden Harder Aug 15 '13 at 10:41
• Just for the record: When the sequence will converge, a logarithmic model is not suitable. – DPF Oct 17 '16 at 20:41

In version 10.2 there is a new experimental function which might be what you are looking for: FindFormula.

I suspect that a genetic programming algorithm (symbolic regression) is behind this new feature.

• Sadly, this dataset is too small for FindFormula to produce sensible results. Some of its' fits are pretty nice, but at least in this case it also produces plenty of fits which are total garbage from an intuitive standpoint. I believe FindFormula needs datasets to be at least a magnitude larger not to suffer from crazy over-fitting. It's also notable that FindFormula depends on randomness on its' search; it may return different results on every invocation. – kirma Jul 18 '15 at 6:47

Functions are like vectors. Actually you can define a vector space over functions. We can describe any vector in terms of 3 independent vector which may not be orthogonal to each other. Similarly, you can fit a function in terms of other linearly independent functions. The easiest case is fitting to a polynomial of order n. Depending on how well your data can be fit you can set n. Another example is fitting to a series of Sine and Cose functions(Discrete Fourier transform). One other example is fitting to Gaussian functions with different mean and standard deviation.

data = {{1, 0.08888888888888872}, {2, 0.13842641081508972}, {3,
0.17153280014540232}, {4, 0.19586894934728782}, {5,
0.21482500502852542}, {6, 0.23017213935351592}, {7,
0.24294479920054762}, {8, 0.25379708095478332}, {9,
0.26316771779066082}, {10, 0.27136463872018062}, {11,
0.27861184976714762}, {12, 0.28507709754351612}, {13,
0.29088903838678592}, {14, 0.29614834727916052}, {15,
0.30093516063430942}, {16, 0.30531421254734282}, {17,
0.30933847047870212}, {18, 0.31305176609215322}, {19,
0.3164907360488469}};


Fit to Cos functions:

model2 = Sum[Subscript[a, n]*Cos[(2*Pi)/T*n*x], {n, 0, 20}];
sol = FindFit[data , {model2, T > 100},  Flatten[{Table[{Subscript[a, i]}, {i, 0, 20}], T}], x]


Fit to polynomial:

model1 = Sum[Subscript[a, i]*x^i, {i, 0, 5}];
sol = FindFit[data , {model1},  Flatten[{Table[{Subscript[a, i]}, {i, 0, 5}]}], x]


Fit to Gaussian functions:

Here I took only 3 Gaussian function, for better fit either you need more Gaussian functions or a better initial guess and constraints.

How about a mixture of smoothing and curve fitting? This is based on a previous post of mine here. We use a best interpolation function. Here is your data.

data = {{1, 0.08888888888888872}, {2, 0.13842641081508972}, {3,
0.17153280014540232}, {4, 0.19586894934728782}, {5,
0.21482500502852542}, {6, 0.23017213935351592}, {7,
0.24294479920054762}, {8, 0.25379708095478332}, {9,
0.26316771779066082}, {10, 0.27136463872018062}, {11,
0.27861184976714762}, {12, 0.28507709754351612}, {13,
0.29088903838678592}, {14, 0.29614834727916052}, {15,
0.30093516063430942}, {16, 0.30531421254734282}, {17,
0.30933847047870212}, {18, 0.31305176609215322}, {19,
0.3164907360488469}};


Now define a number of control points. This number must be less than the number of your data points. The more control points the closer the fit to your data but the less smooth the fitted curve.

nOfControlPoints = 9;
controlPoints =
Subdivide[#1, #2, nOfControlPoints - 1] & @@ MinMax[data[[;; , 1]]];
ListPlot[data, Epilog -> {Red, Point[{#, 0}] & /@ controlPoints},
Frame -> True, Axes -> False]


Now fit the model.

   model[y : {__Real}] := Interpolation[Transpose[{controlPoints, y}]];
nlm = NonlinearModelFit[data, model[Array[y, nOfControlPoints]][x],
Array[y, nOfControlPoints], x];


Plot the data and the fitted curve.

   Plot[nlm["Function"][x], {x, data[[1, 1]], data[[-1, 1]]},
Epilog -> {Point[data]}, Frame -> True]


The advantage of this method is that it avoids the use of polynomials which always give a poor fit when the order is high. Very large data sets can be fitted with a smooth curve using this method. Hope this helps.

• Interesting approach, but I find the term "model" kind of misleading, as it is just a smoothing and no "real" model, motivated by physics or other processes. – DPF Oct 17 '16 at 18:04
• @DPF I agree with your comment. If you have some physics then you should try and get that into the model. However, if you don't know why the function behaves as it does then at least you can do some maths with this model. If you blindly fit polynomials that usually goes wrong. – Hugh Oct 17 '16 at 18:28
• For this case are very powerful interpolation tools available. – DPF Oct 17 '16 at 19:05
• @DPF Sorry is that a question or a statement? – Hugh Oct 17 '16 at 19:49
• My comment has no question mark, that makes it a statement ;). I recommend not to use the terms "fit" and "model" for the process of interpolation. – DPF Oct 17 '16 at 20:43

Is that what you mean? Model 1: y= a0 + a1*ln(x), a0 = 0.0874214, a1 = 0.0789488

Model 2: y= a0 + a1*x^(1/7) + a2*(ln(x))^5 a0= -4.04E-01, a1 = 0.4928045, a2 = -1.36E-04

Calculated using ndCurveMaster

• Did you use Mathematica to carry out these fitting calculations? – MarcoB May 22 '17 at 13:17