# Fitting plot and data to an equation

If I have the following data:

data={{2, 66.7635}, {Log[300]/Log[10], 69.9679}, {Log[600]/Log[10],
71.54}, {3, 72.2428}, {-2.30103, 54.0023}, {-(Log[60]/Log[10]),
55.1941}, {-(Log[20]/Log[10]), 56.0038}, {-1,
56.9497}, {-(Log[6]/Log[10]), 57.305}, {-(Log[10/3]/Log[10]),
57.7213}, {-(Log[2]/Log[10]), 58.2489}, {-2.30103,
54.0367}, {-(Log[60]/Log[10]), 55.1157}, {-(Log[20]/Log[10]),
56.1704}, {-1, 56.7117}, {-(Log[6]/Log[10]),
57.2506}, {-(Log[10/3]/Log[10]), 57.7097}, {-(Log[2]/Log[10]),
58.1068}}


Which looks like this plotted:

I have two questions:

1) How can I fit and plot the fit of this data based on the following equation?

: where Tf'_ref=57.2506 , q_ref=0.166667 and c1 and c2 are the fitting parameters. Also, notice that data is Tf' vs Log q in the equation. "Log" in the equation refers to based 10 logarithm and not to natural logarithm.

2) How can I find the values of c1 and c2 which are the fitting parameters.

The fitting (orange line) is supposed to look like this (done in excel):

with fitting parameters c1=9.43903909249581 and c2=23.1214485816819

EDIT: I tried using NonLinearFitModel like this: Table[{NonlinearModelFit[data, Logqref - ((c1*(data[[i, 2]] - Tfref))/(c2*(data[[i, 2]] - Tfref))), {{c1, 8.6}, {c2, 17.2}}, x]; }, {i, 1, 11}] but this does not work. The reason I tried this is because data[[i, 2]] represents Tf' in the equation. Here Logref=Log10[0.16667]

EDIT2: When I do it in Excel c1=9.43903909249581 and c2=23.1214485816819. When I put this parameters into the equation they seem to fit the equation very well as well. Since the parameters found by @Bob Hanlon seems to fit the data very well as well, 3) How can I know what is the best parameters to fit and how could mathematica also find the parameters I found in excel, which seems to have a lower sum of errors squared?

• @JimB I think that 'NonLinearModelFit'. is the best for this. I just do not know exactly how to implement it for this particular problem. Could you help me with this?
– John
Commented Jun 1, 2020 at 22:05
• @JimB yes. I have used the function before. Even you have helped me in other occasions that have needed this. It's just that for this case in particular it is not working for me. There is something wrong I am doing and that's why I am asking for help with people with more experience and knowledge than me on this. Thanks
– John
Commented Jun 1, 2020 at 22:10
• @JimB I tried like this: Table[{NonlinearModelFit[data, Logqref - ((c1*(data[[i, 2]] - Tfref))/(c2*(data[[i, 2]] - Tfref))), {{c1, 8.6}, {c2, 17.2}}, x]; }, {i, 1, 11}]. This is not working because what I am trying is to use data[[i,2]] to get the Tf' and fit them but I do not think this is the right approach. Here Logref=Log10[0.16667]
– John
Commented Jun 1, 2020 at 22:25
• @JimB thanks! I put it in the post as an EDIT
– John
Commented Jun 1, 2020 at 22:36

Clear["Global*"]

data = {{2, 66.7635}, {Log[300]/Log[10], 69.9679}, {Log[600]/Log[10],
71.54}, {3, 72.2428}, {-2.30103, 54.0023}, {-(Log[60]/Log[10]),
55.1941}, {-(Log[20]/Log[10]), 56.0038}, {-1,
56.9497}, {-(Log[6]/Log[10]), 57.305}, {-(Log[10/3]/Log[10]),
57.7213}, {-(Log[2]/Log[10]), 58.2489}, {-2.30103,
54.0367}, {-(Log[60]/Log[10]), 55.1157}, {-(Log[20]/Log[10]),
56.1704}, {-1, 56.7117}, {-(Log[6]/Log[10]),
57.2506}, {-(Log[10/3]/Log[10]), 57.7097}, {-(Log[2]/Log[10]),
58.1068}};


EDIT:

eqn = ((log10q - Log10[qref]) == c1*(Tfp - Tfpref)/(c2 + (Tfp - Tfpref)));


Solve the equation for Tfp to obtain the model

model = Tfp /. Solve[eqn, Tfp][[1]] // FullSimplify

(* Tfpref + c2 (-1 + (c1 Log[10])/((c1 - log10q) Log[10] + Log[qref])) *)

const = {Tfpref -> 57.2506, qref -> 0.166667};


Substituting the constants into the model

model2 = model /. (const // Rationalize) // FullSimplify

(* 286253/5000 +
c2 (-1 + (c1 Log[10])/((-6 + c1 - log10q) Log[10] + Log[166667])) *)


Using NonlinearModelFit with a constraint on the parameters

nlm = NonlinearModelFit[data,
{model2, c1 > 5, c2 > 5}, {c1, c2}, log10q];

param = nlm["BestFitParameters"]

(* {c1 -> 9.29797, c2 -> 22.629} *)

nlm["ParameterTable"] // Quiet


confidInterval = Thread[{c1, c2} -> Around@*Interval /@
nlm["ParameterConfidenceIntervals"]]

(* {c1 -> Around[9.297969154154664, 1.0182007406816869],
c2 -> Around[22.62894607083057, 3.89519370692895]} *)

Plot[nlm[log10q],
{log10q, Min[data[[All, 1]]], Max[data[[All, 1]]]},
Epilog -> {Red, AbsolutePointSize[4], Point[data]},
Frame -> True,
Axes -> False,
GridLines -> Automatic,
GridLinesStyle -> Lighter[Gray, .8],
FrameLabel -> (Style[#, 14, Bold] & /@
{HoldForm@Log10["q (K/s)"],
Row[{Subscript[T, f'], " (", Degree, " C)"}]})]


• Bob Hanlon thank you very much! The fit is really good.! There is something I don't understand. Where did you use qref in the code?. It looks like this part of the equation is not included.
– John
Commented Jun 1, 2020 at 23:32
• Bob Hanlon! Could you please check the new edit I posted?. In excel I found c1=9.43903909249581 and c2=23.1214485816819 which seems to have a lower sum of error squares than your parameters (which also fit the data well). Is it possible that Mathematica can also find this parameters using your code as they seem to have less error to fit the data?.
– John
Commented Jun 2, 2020 at 0:30
• I think the problem with the fit and not getting the same parameters has to do with something @tad said. In your code you are using the data in the x-axis as the input for Tfp rather than that in the y-axis ("Tf'"). Also, I am not sure if you are using qref in your code. Could you clarify this if you don't mind?
– John
Commented Jun 2, 2020 at 0:49
• Initial answer was wrong. Corrected. Note that I used Log10. Commented Jun 2, 2020 at 1:55
• Bob! Thank you very much ! This answer is great and works perfect !
– John
Commented Jun 2, 2020 at 2:20

Your example is a Table of nonlinear fits rather than applying NonlinearModelFit to all the data at once.

Two issues in using NonlinearModelFit in your case:

1) your equation gives Log[q] in terms of Tf whereas NonlinearModelFit needs an equation for the output, in this case Tf, in terms of the input, i.e., Log[q].

2) the Tf values in your data extend below the reference temperature, so unless C2 is large enough, the fit could divide by zero somewhere in the range of temperatures in your data.

For issue 1), you could either reverse the order of your data, fitting Log[q] in terms of Tf, or rewrite your equation to give Tf in terms of Log[q]. For issue 2), NonlinearModelFit may require specifying initial guesses for C1 and C2.

Here's how to use NonlinearModelFit by rewriting your equation, using logq to refer to Log[q]:

expr = Simplify[Tf /. Solve[
PowerExpand@Log[q/qRef] == (C1 (Tf - TfRef))/(
C2 + (Tf - TfRef)), Tf][[1]] /.
Log[q] -> logq /. {TfRef -> 57.2506, qRef -> 0.166667}]


To fit to your data, I use initial guesses of 10 for the parameters:

fit = NonlinearModelFit[data, expr, {{C1, 10}, {C2, 10}}, logq]


To get fit parameters:

fit["BestFitParameters"]


and to plot:

Show[ListPlot[data], Plot[fit[logq], {logq, -3, 3}]]


Comparing the fit with the data isn't as close as the Excel plot you provide. Is it possible the reference q value is for log base 10, i.e., Log10[q] in your equation?

• Thank you tad. It should fit well depending on c1 and c2. See the answer provided by @Bob Hanlon
– John
Commented Jun 1, 2020 at 23:27
• Yes, that's a good fit. Note that it uses Tfp as the variable on the horizontal axis, which you call Log[q]. Possibly in your equation you meant to exchange Tf and Log[q]?
• thanks. You mean vertical?. He uses Tfp which corresponds to Tf' in the equation which is variable and corresponds to the temperatures in the y-axis. The one which is constant is Tfref
• tad notice that your fit gets and error that reads "NonlinearModelFit::sszero: The step size in the search has become less than the tolerance prescribed by the PrecisionGoal option, but the gradient is larger than the tolerance specified by the AccuracyGoal option. There is a possibility that the method has stalled at a point that is not a local minimum." I think you are in the right track. Remember that the fitting parameters should be c1=9.43903909249581 and c2=23.1214485816819. If you put that in your model using the y-axis as inputs you should get a great fit & solve my problem finally