-1
$\begingroup$

I have a two column data which is y vs x. I want to linearize the data by this formula 1/(x-b) but I don't know how to determine the b value such that the ln(y) vs 1/(x-b) becomes a linear line. So I script the following code to plot the ln(y) vs 1/(x-b) with changing the b value manually and by looking at the ln(y) vs 1/(x-b) graph to find the best linear behavior. Do you know a better way of doing it instead of changing the b value manually?

x = {331,334,335,336};
y = {10,50,100,1000};
b = 290;
Xinv = 1/(x - b)
lnY = N[Log[y]];
(data = Transpose[{Xinv, lnY}]) // MatrixForm;
ListPlot[data, PlotMarkers -> {"O"}, 
 PlotStyle -> {Darker@Green, PointSize[3]}]
nlm = NonlinearModelFit[data, a*x + b, {a, b}, x];
Show[ListPlot[data, PlotMarkers -> "\!\(\*
StyleBox[\"O\",\nFontWeight->\"Plain\"]\)"], Plot[nlm[x], {x, -1, 2}],
  Frame -> True]
$\endgroup$
2
  • 1
    $\begingroup$ I think the problem is that x and b are used as arguments to NonlinearModelFit. Try NonlinearModelFit[data, a*s + t, {a, t}, s] $\endgroup$ – Rohit Namjoshi Feb 19 '20 at 19:30
  • $\begingroup$ Dear Rohit Namjoshi, the goal is to find the best value of "b" to obtain the best linear line for the lnY vs Xinv data $\endgroup$ – Nini Feb 19 '20 at 20:26
1
$\begingroup$

You assign values to a and x and also use the same names in 2nd, 3rd, and 4th arguments of NonlinearModelFit. You shouldn't do that because they get evaluated before NonlinearModelFit sees them. You need to use different names.

x = {331, 334, 335, 336};
y = {10, 50, 100, 1000};
b = 290;
Xinv = 1/(x - b);
lnY = N[Log[y]];
data = Transpose[{Xinv, lnY}]
nlm = NonlinearModelFit[data, a u + bb, {a, bb}, u]

fit

Show[
  ListPlot[data],
  Plot[nlm[x], {x, -1, 2}], 
  Frame -> True]

plot

Update

OK, I think I finally understand what you want. Based on that improved understanding, I suggest you try using `` to find the value of b that gives the best fit to your data. Like so:

Block[{invX, data, nlm},
  With[{xx = {331, 334, 335, 336}, lnY = N[Log[{10, 50, 100, 1000}]]},
    invX[b_] = 1/(xx - b);
    data[b_] = N[Transpose[{invX[b], lnY}]];
    nlm[b_?NumericQ] := NonlinearModelFit[data[b], a x + b, {a}, x]];
    Module[{bestB, pts, line, xmin, xmax},
      bestB = NArgMax[nlm[b]["AdjustedRSquared"], b];
      pts = data[bestB];
      line = nlm[bestB];
      xmin = pts[[1, 1]];
      xmax = pts[[-1, 1]];
      Show[
        ListPlot[pts,
          PlotStyle -> {Red, AbsolutePointSize[6]},
          PlotLabel -> Row[{"b = ", bestB."\n"}]],
        Plot[line[x], {x, xmin, xmax}],
        Frame -> True]]]

plot

$\endgroup$
4
  • $\begingroup$ The code works but my main question is to find the "b" value to give me the best linear behavior of lnY vs. Xinv. Here I picked b = 290 which gives almost a linear behavior but there can be many b values but I don't know how to implement in Mathematica to obtain the best linear line of lnY vs. Xinv. $\endgroup$ – Nini Feb 21 '20 at 16:04
  • $\begingroup$ @Nini. Take a look at the update I made. Does it do what you want? $\endgroup$ – m_goldberg Feb 21 '20 at 19:13
  • $\begingroup$ Hi @m_goldberg, the code is nice but if you try "b = 325" it gives you the lowest Standard Errors rather than "b = 152.241". Would it be possible to improve the code? $\endgroup$ – Nini Feb 22 '20 at 22:58
  • $\begingroup$ @Nini. The fit residuals for b = 154.24 are {0.396262, -0.536585, -0.672113, 0.810915}. For b = 325, they are {106.662, -34.8486, -62.7794, -83.8964}. I don't see how b = 325 produces a better fit. Even if I use the standardized residuals in place of the fit residuals I get a better score for b = 154.24. Perhaps there is a error in your calculations. $\endgroup$ – m_goldberg Feb 23 '20 at 2:43

Not the answer you're looking for? Browse other questions tagged or ask your own question.