# Finding fit function for a given data

In the following, there is some data given. How to find the best fit function of one variable with multiple parameters that best describe this data? It's better to check the agreement on the ListLogLogPlot.

Here is the data:

In the following, there is some data given. How to find the best fit function of one variable with multiple parameters that best describe this data? It's better to check the agreement on the ListLogLogPlot.

Here is the data:

In the following, there is some data given. How to find the best fit function of one variable with multiple parameters that best describe this data? It's better to check the agreement on the ListLogLogPlot.

Here is the data:

data = {{0.1, 0.0153057}, {0.2, 0.0336045}, {0.3, 0.0532532}, {0.4,
0.0738468}, {0.5, 0.0951825}, {0.6, 0.117137}, {0.7,
0.139625}, {0.8, 0.162585}, {0.9, 0.185971}, {1., 0.209746}, {1.1,
0.23388}, {1.2, 0.258346}, {1.3, 0.283125}, {1.4, 0.308199}, {1.5,
0.33355}, {1.6, 0.359167}, {1.7, 0.385036}, {1.8, 0.411146}, {1.9,
0.437489}, {2., 0.464054}, {2.1, 0.490835}, {2.2, 0.517823}, {2.3,
0.545013}, {2.4, 0.572397}, {2.5, 0.599971}, {2.6, 0.627728}, {2.7,
0.655664}, {2.8, 0.683775}, {2.9, 0.712056}, {3., 0.740503}, {3.1,
0.769113}, {3.2, 0.797881}, {3.3, 0.826805}, {3.4, 0.855881}, {3.5,
0.885106}, {3.6, 0.914477}, {3.7, 0.943992}, {3.8, 0.973649}, {3.9,
1.00344}, {4., 1.03337}, {4.1, 1.06344}, {4.2, 1.09364}, {4.3,
1.12396}, {4.4, 1.15442}, {4.5, 1.185}, {4.6, 1.2157}, {4.7,
1.24653}, {4.8, 1.27748}, {4.9, 1.30855}, {5., 1.33973}, {5.1,
1.37103}, {5.2, 1.40245}, {5.3, 1.43398}, {5.4, 1.46562}, {5.5,
1.49737}, {5.6, 1.52923}, {5.7, 1.5612}, {5.8, 1.59327}, {5.9,
1.62545}, {6., 1.65774}, {6.1, 1.69013}, {6.2, 1.72262}, {6.3,
1.75521}, {6.4, 1.7879}, {6.5, 1.82069}, {6.6, 1.85359}, {6.7,
1.88657}, {6.8, 1.91966}, {6.9, 1.95284}, {7., 1.98611}, {7.1,
2.01948}, {7.2, 2.05295}, {7.3, 2.0865}, {7.4, 2.12015}, {7.5,
2.15389}, {7.6, 2.18771}, {7.7, 2.22163}, {7.8, 2.25564}, {7.9,
2.28973}, {8., 2.32391}, {8.1, 2.35818}, {8.2, 2.39253}, {8.3,
2.42697}, {8.4, 2.4615}, {8.5, 2.4961}, {8.6, 2.5308}, {8.7,
2.56557}, {8.8, 2.60043}, {8.9, 2.63537}, {9., 2.67039}, {9.1,
2.70549}, {9.2, 2.74067}, {9.3, 2.77593}, {9.4, 2.81127}, {9.5,
2.84669}, {9.6, 2.88219}, {9.7, 2.91776}, {9.8, 2.95341}, {9.9,
2.98914}, {10., 3.02495}, {10.1, 3.06083}, {10.2, 3.09678}, {10.3,
3.13281}, {10.4, 3.16892}, {10.5, 3.2051}, {10.6, 3.24135}, {10.7,
3.27768}, {10.8, 3.31408}, {10.9, 3.35055}, {11., 3.38709}, {11.1,
3.42371}, {11.2, 3.46039}, {11.3, 3.49715}, {11.4, 3.53398}, {11.5,
3.57087}, {11.6, 3.60784}, {11.7, 3.64488}, {11.8, 3.68199}, {11.9,
3.71916}, {12., 3.7564}, {12.1, 3.79371}, {12.2, 3.83109}, {12.3,
3.86854}, {12.4, 3.90605}, {12.5, 3.94363}, {12.6, 3.98128}, {12.7,
4.01899}, {12.8, 4.05677}, {12.9, 4.09461}, {13., 4.13252}, {13.1,
4.1705}, {13.2, 4.20854}, {13.3, 4.24664}, {13.4, 4.28481}, {13.5,
4.32304}, {13.6, 4.36133}, {13.7, 4.39969}, {13.8, 4.43811}, {13.9,
4.47659}, {14., 4.51514}, {14.1, 4.55374}, {14.2, 4.59241}, {14.3,
4.63114}, {14.4, 4.66994}, {14.5, 4.70879}, {14.6, 4.7477}, {14.7,
4.78668}, {14.8, 4.82571}, {14.9, 4.86481}, {15., 4.90396}, {15.1,
4.94318}, {15.2, 4.98245}, {15.3, 5.02179}, {15.4, 5.06118}, {15.5,
5.10063}, {15.6, 5.14014}, {15.7, 5.17971}, {15.8, 5.21933}, {15.9,
5.25902}, {16., 5.29876}, {16.1, 5.33856}, {16.2, 5.37842}, {16.3,
5.41833}, {16.4, 5.4583}, {16.5, 5.49833}, {16.6, 5.53841}, {16.7,
5.57855}, {16.8, 5.61875}, {16.9, 5.659}, {17., 5.6993}, {17.1,
5.73967}, {17.2, 5.78008}, {17.3, 5.82056}, {17.4, 5.86108}, {17.5,
5.90167}, {17.6, 5.9423}, {17.7, 5.98299}, {17.8, 6.02374}, {17.9,
6.06454}, {18., 6.10539}, {18.1, 6.1463}, {18.2, 6.18726}, {18.3,
6.22827}, {18.4, 6.26934}, {18.5, 6.31046}, {18.6, 6.35163}, {18.7,
6.39285}, {18.8, 6.43413}, {18.9, 6.47546}, {19., 6.51684}, {19.1,
6.55827}, {19.2, 6.59976}, {19.3, 6.64129}, {19.4, 6.68288}, {19.5,
6.72452}, {19.6, 6.76621}, {19.7, 6.80795}, {19.8, 6.84974}, {19.9,
6.89159}, {20., 6.93348}, {20.1, 6.97542}, {20.2, 7.01742}, {20.3,
7.05946}, {20.4, 7.10156}, {20.5, 7.1437}, {20.6, 7.18589}, {20.7,
7.22814}, {20.8, 7.27043}, {20.9, 7.31277}, {21., 7.35516}, {21.1,
7.3976}, {21.2, 7.44009}, {21.3, 7.48262}, {21.4, 7.52521}, {21.5,
7.56784}, {21.6, 7.61052}, {21.7, 7.65325}, {21.8, 7.69603}, {21.9,
7.73886}, {22., 7.78173}, {22.1, 7.82465}, {22.2, 7.86762}, {22.3,
7.91064}, {22.4, 7.9537}, {22.5, 7.99681}, {22.6, 8.03997}, {22.7,
8.08317}, {22.8, 8.12642}, {22.9, 8.16972}, {23., 8.21307}, {23.1,
8.25646}, {23.2, 8.29989}, {23.3, 8.34337}, {23.4, 8.3869}, {23.5,
8.43048}, {23.6, 8.4741}, {23.7, 8.51776}, {23.8, 8.56147}, {23.9,
8.60523}, {24., 8.64903}, {24.1, 8.69288}, {24.2, 8.73677}, {24.3,
8.78071}, {24.4, 8.82469}, {24.5, 8.86872}, {24.6, 8.91279}, {24.7,
8.95691}, {24.8, 9.00107}, {24.9, 9.04527}, {25., 9.08952}, {25.1,
9.13381}, {25.2, 9.17815}, {25.3, 9.22253}, {25.4, 9.26695}, {25.5,
9.31142}, {25.6, 9.35593}, {25.7, 9.40049}, {25.8, 9.44509}, {25.9,
9.48973}, {26., 9.53442}, {26.1, 9.57914}, {26.2, 9.62391}, {26.3,
9.66873}, {26.4, 9.71358}, {26.5, 9.75848}, {26.6, 9.80343}, {26.7,
9.84841}, {26.8, 9.89344}, {26.9, 9.93851}, {27., 9.98362}, {27.1,
10.0288}, {27.2, 10.074}, {27.3, 10.1192}, {27.4, 10.1645}, {27.5,
10.2098}, {27.6, 10.2552}, {27.7, 10.3006}, {27.8, 10.346}, {27.9,
10.3915}, {28., 10.437}, {28.1, 10.4826}, {28.2, 10.5282}, {28.3,
10.5739}, {28.4, 10.6195}, {28.5, 10.6653}, {28.6, 10.7111}, {28.7,
10.7569}, {28.8, 10.8027}, {28.9, 10.8486}, {29., 10.8946}, {29.1,
10.9405}, {29.2, 10.9865}, {29.3, 11.0326}, {29.4, 11.0787}, {29.5,
11.1248}, {29.6, 11.171}, {29.7, 11.2172}, {29.8, 11.2635}, {29.9,
11.3098}, {30., 11.3561}, {30.1, 11.4025}, {30.2, 11.4489}, {30.3,
11.4953}, {30.4, 11.5418}, {30.5, 11.5884}, {30.6, 11.6349}, {30.7,
11.6815}, {30.8, 11.7282}, {30.9, 11.7749}, {31., 11.8216}, {31.1,
11.8684}, {31.2, 11.9152}, {31.3, 11.962}, {31.4, 12.0089}, {31.5,
12.0558}, {31.6, 12.1028}, {31.7, 12.1498}, {31.8, 12.1968}, {31.9,
12.2439}, {32., 12.291}, {32.1, 12.3381}, {32.2, 12.3853}, {32.3,
12.4325}, {32.4, 12.4798}, {32.5, 12.5271}, {32.6, 12.5744}, {32.7,
12.6218}, {32.8, 12.6692}, {32.9, 12.7166}, {33., 12.7641}, {33.1,
12.8116}, {33.2, 12.8592}, {33.3, 12.9068}, {33.4, 12.9544}, {33.5,13.0021}, {33.6, 13.0498}, {40.2, 16.2765}, {40.3, 16.3266}, {40.4, 16.3766}, {40.5, 16.4267}, {40.6, 16.4769}, {40.7,
16.527}, {40.8, 16.5772}, {40.9, 16.6274}, {41., 16.6777}, {41.1,
16.728}, {41.2, 16.7783}, {41.3, 16.8286}, {41.4, 16.879}, {41.5,
16.9295}, {41.6, 16.9799}, {41.7, 17.0304}, {41.8, 17.0809}, {41.9,
17.1314}, {42., 17.182}, {42.1, 17.2326}, {42.2, 17.2833}, {42.3,
17.3339}, {42.4, 17.3846}, {42.5, 17.4354}, {42.6, 17.4862}, {42.7,
17.537}, {42.8, 17.5878}, {42.9, 17.6386}, {43., 17.6895}, {43.1,
17.7405}, {43.2, 17.7914}, {43.3, 17.8424}, {43.4, 17.8934}, {43.5,
17.9445}, {43.6, 17.9956}, {43.7, 18.0467}, {43.8, 18.0978}, {43.9,
18.149}, {44., 18.2002}, {44.1, 18.2514}, {44.2, 18.3027}, {44.3,
18.354}, {44.4, 18.4053}, {44.5, 18.4567}, {44.6, 18.5081}, {44.7,
18.5595}, {44.8, 18.6109}, {44.9, 18.6624}, {45., 18.7139}, {45.1,
18.7655}, {45.2, 18.817}, {45.3, 18.8686}, {45.4, 18.9203}, {45.5,
18.9719}, {45.6, 19.0236}, {45.7, 19.0754}, {45.8, 19.1271}, {45.9,
19.1789}, {46., 19.2307}, {46.1, 19.2826}, {46.2, 19.3344}, {46.3,
19.3863}, {46.4, 19.4383}, {46.5, 19.4902}, {46.6, 19.5422}, {46.7,
19.5942}, {46.8, 19.6463}, {46.9, 19.6984}, {47., 19.7505}, {47.1,
19.8026}, {47.2, 19.8548}, {47.3, 19.907}, {47.4, 19.9592}, {47.5,
20.0115}, {47.6, 20.0638}, {47.7, 20.1161}, {47.8, 20.1684}, {47.9,
20.2208}, {48., 20.2732}, {48.1, 20.3257}, {48.2, 20.3781}, {48.3,
20.4306}, {48.4, 20.4831}, {48.5, 20.5357}, {48.6, 20.5883}, {48.7,
20.6409}, {48.8, 20.6935}, {48.9, 20.7462}, {49., 20.7989}, {49.1,
20.8516}, {49.2, 20.9043}, {49.3, 20.9571}, {49.4, 21.0099}, {49.5,
21.0628}, {49.6, 21.1156}, {49.7, 21.1685}, {49.8, 21.2214}, {49.9,
21.2744}, {50., 21.3274}};


Thanks a lot!

• The graph you just added: what is it?
– JimB
Mar 9, 2022 at 14:57
• This is an "AICc" of different data. Does this show that the model function can have a polynomial of the order greater than 200? Mar 9, 2022 at 15:12
• That figure needs explanation and should really be part of a different question and even at that better asked at CrossValidated. But in the meantime...it appears from that figure that a polynomial of degree 25 or so is the maximum you should consider. And if this is your first time hearing of AIC and if this analysis has any importance, you really need to consult with a statistician.
– JimB
Mar 9, 2022 at 17:06
• @JimB: Yes, I am using AIC first time. The problem is it's really complicated to post the details related to this plot separately. Anyway, the idea of AIC would help me enough. Mar 9, 2022 at 18:44

How you intend to use the result and how good the result needs to be matters. (For example, will you or your employer get sued if the predictions are wrong enough to cause injury?)

Given the apparent low level of variation along an apparent smooth curve if you're going to make predictions only using Mathematica and those predictions don't need to be outside of the observed data, just use Interpolation:

f = Interpolation[data]
f[50]
(* 21.3274 *)


Or consider a fit with a quadratic polynomial on the logs of your data:

lm = LinearModelFit[Log[data], {x, x^2}, x];
Show[ListLogLogPlot[data, PlotStyle -> PointSize[0.015]],
LogLogPlot[Exp[lm[Log[x]]], {x, Min[data[[All, 1]]], Max[data[[All, 1]]]}, PlotStyle -> Red]]


The standard error of estimate is

lm["EstimatedVariance"]^0.5
(* 0.00420636 *)


Is that small enough to say you have a good enough fit? Rather than interpret that number on the log scale, you can interpret that as plus-or-minus 0.422% of any prediction (with 0.422% = 100*Exp[0.00420636]).

But what about the lack of fit with the above model? Look at the residuals vs. the predictor:

ListLogLinearPlot[Transpose[{data[[All, 1]], lm["FitResiduals"]}],
PlotStyle -> PointSize[0.015], PlotRange -> All]


This plot says that if the standard error of estimate is not small enough, there is still a strong signal in the residuals. In other words, there's certainly a better model available. Maybe adding in more polynomial terms. Maybe adding a sine wave?

But all of this really needs you to have some idea as to how good you need the prediction to be. That is not an intrinsic property of the data.

If polynomials are the only class of models you want to consider, then a reasonable guideline to help you tell when you should stop adding terms is to use $$AIC_c$$.

aicc = Table[{k, LinearModelFit[Log[data], Table[x^i, {i, k}], x]["AICc"]}, {k, 1, 20}];
ListPlot[aicc]


This plot suggests that once you get past 10 or 11 polynomial terms, you're wasting your time. You could certainly have fewer terms if any of those models meet the maximum standard of error you're willing to tolerate.

There are certainly better regression modeling strategies. See Frank Harrell's book Regression Modeling Strategies.

• Great! The rest were okay, however, the AICc is new and quite interesting for me! Great to know this. Two points: 1) Could you please see the plot I uploaded with the question above. What does this AICc tell? Remember, this is for another data, not with the main question above. 2) Can we extract the analytical function from the "Interpolation"? Interpolation is an ideal command but the issue is that it does not work with the "Integrate" (the analytical one) command in further steps. Mar 9, 2022 at 13:47
• "it does not work with the Integrate (the analytical one) command". Sure it does: Integrate[f[x], {x, 40, 45}] gets you 87.1933.
– JimB
Mar 9, 2022 at 22:58
• Why would you want to integrate over y when there is no y in f[x]?
– JimB
Mar 10, 2022 at 0:27
• @SciJewel Nevermind. I understand now about the integration.
– JimB
Mar 10, 2022 at 5:30

Your data have a very steep increase in the beginning and a flat end. To fit a single function is therefore difficult. It is better to split the data and make 2 independent fits. For a unknown model function "FindFormul"a is helpful:

The first fit:

nn = 30;
fun1 =
FindFormula[data[[;; nn]], PerformanceGoal -> "Quality",
SpecificityGoal -> Infinity]
pl1 = LogPlot[fun1[x], {x, 0.1, data[[nn, 1]]}];
pl2 = ListLogPlot[data[[;; nn]], PlotStyle -> Red];
Show[pl2, pl1]


And the second fit:

fun2 =
FindFormula[data[[nn + 1 ;; -1]], PerformanceGoal -> "Quality",
SpecificityGoal -> Infinity]
pl1 = LogPlot[fun2[x], {x, data[[nn + 1, 1]], 50}];
pl2 = ListLogPlot[data[[nn + 1 ;; -1]], PlotStyle -> Red];
Show[pl2, pl1]


Then we may combine the two fits:

fun0[x_] =
Piecewise[{{fun1[x], x <= data[[nn, 1]]}, {fun2[x],
x > data[[nn, 1]]}}];
LogPlot[fun0[x], {x, 0.1, 50},
Epilog -> {PointSize[0.005], ,
Point[{#[[1]], Log[#[[2]]]} & /@ data], PlotRange -> All}]


Where to split the data needs some fiddling and you may improve this yourself.

• What is the final function of this method? When I run, the function does not show up. Feb 28, 2022 at 14:04
• fun0 is the final function. Note, that you must define the variable "data" Feb 28, 2022 at 14:31
• Got it! But unfortunately, the fit function is too complicated and with many terms. I was looking for something simple with less terms, no matter if it's a piece-wise function. thanks any way! Feb 28, 2022 at 15:02
• You can set SpecificityGoal e.g. to 1 or 2 or whatever to get a simpler function. Look it up in the help of FindFormula. Feb 28, 2022 at 15:54
• Thanks@ Daniel! Feb 28, 2022 at 18:26
ListPlot[data]
FindFit[data, a x Log[b + c x], {a, b, c}, x]


This gives you the results for a, b, and c. And you can plot them:

Plot[0.12532133496079953 x
Log[6.413210078405174 + 0.4709352365286802 x], {x, 0, 50}]


Or if you need data to put it in the ListPlot do this:

data2 = Table[{x, 0.12532133496079953 x
Log[6.413210078405174 + 0.4709352365286802 x]}, {x, 0, 50, 0.5}]


• The FindFit run gives me the following error message: "The function value {-0.0912959+0.0405747\ I,-0.100308+0.0452071\ \ I,-0.10931+0.049896847149746605 I," with complex solutions. Feb 28, 2022 at 14:28
• try to clear the kernel, put in the data and run the FindFit function again. Mar 1, 2022 at 9:47
• Thanks@ Philipp! This is nice and more simple, but there is still one issue there. If you compare the fit data with the original data on LogLogPlot, you will see that they agree well above 5 on the x-axis, but below 5, they deviate a lot. Thanks! Mar 3, 2022 at 11:37

Extremely hacky, I used MyCurveFit (20 data point free fit) on these selected log points

Part[Transpose[{data[[All, 1]], Log@data[[All, 2]]}],
{1, 3, 5, 9, 14, 23, 33, 45, 70, 90, 130, 150,
180, 200, 240, 280, 350, 400, 450, 500}] // TableForm


which returned

y = 101.9456 + (-44.27283 - 101.9456)/(1 +
(x/13749720000.000002)^0.03793334)


So using the following I got a pretty good fit.

g[x_] := E^(101.9456 + (-44.27283 - 101.9456)/(1 +
(x/13749720000.000002)^0.03793334))

Show[Plot[g[x], {x, 0.1, 50}], ListLinePlot[data, PlotStyle -> Red]]


The first 60 log points

pl1 = LogPlot[g[x], {x, 0.1, data[[60, 1]]}];
pl2 = ListLogPlot[data[[;; 60]], PlotStyle -> Red];
Show[pl2, pl1]


modelForm=a+b*x (c+x)^(1/4)


Then we use NonlinearModelFit to fit the model to the data and get the parameters.

fittedModel = NonlinearModelFit[data, modelForm, {a, b, c}, x];
fittedModel["BestFitParameters"]


Out: {a -> -0.0126155, b -> 0.15756, c -> 3.59594}

Now we can plot the model predictions and the original data to see how we did.

Show[{ListLogLogPlot[Transpose@{Transpose[data][[1]],fittedModel[#] & /@Transpose[data][[1]]}, PlotRange -> All],ListLogLogPlot[data, PlotStyle -> Red]}]


We can see that there is very close agreement over the entire data range. There is still some error, but the error is pretty small. Depending on the application this may or may not be acceptable.

• Unfortunately, the lower end is more important. Mar 8, 2022 at 10:15
• How do you quantify "the lower end is more important" ? Is it such that only you will know it when you see it? If you have something in mind, you need to give specifics.
– JimB
Mar 8, 2022 at 14:42
• @JimB: Can you see the deviation below 1.5. I mean I need more agreement in the region below 1.5. Mar 9, 2022 at 10:49

If you want the fit to look good on a log-log plot you can try assigning more weight to the smaller values. For example:

func = NonlinearModelFit[data, a x^b + c x^d, {a, b, c, d}, x,
Weights -> 1/data[[All, 2]]]["BestFit"]

(* 0.195162 x^1.10524 + 0.0149097 x^1.55762 *)

GraphicsRow[{Show[
ListLogLogPlot[data, PlotStyle -> {Red, PointSize[0.01]}],
LogLogPlot[func, {x, 0.1, 50}]],
Show[
ListPlot[data, PlotStyle -> {Red, PointSize[0.01]}],
Plot[func, {x, 0.1, 50}]]}]
`

• I hope you're not suggesting that fiddling with weights when there is no a priori reason for weighting is appropriate for fitting data.
– JimB
Mar 7, 2022 at 23:13
• @JimB: How do you choose the model function "a x^b + c x^d" Mar 8, 2022 at 10:18
• @SciJewel I'm not following your question. Someone else chose that particular model. But is your question: "How does one decide on an appropriate model?" or "How does one assess the quality/goodness of a particular model?" Note my concern above is about the error structure which is also a critical component of any model's "formula" and the use/objective of the resulting fit.
– JimB
Mar 8, 2022 at 14:39
• @JimB: Sorry, that was for Simon Woods. Mar 9, 2022 at 10:45
• @Simon Woods: How do you choose the model function "a x^b + c x^d" Mar 9, 2022 at 10:46