I have this code

ntcrr[t_] := E^(a + b/t + c/t^2 + d/t^3)
kelvin[t_] := t + 273.15
a = -13.40956889; b = 4481.798865; c = -150521.6916; d = 1877102.652;
p1 = {30, ntcrr[kelvin[30]]}; p2 = {35, ntcrr[kelvin[35]]};
line := Fit[{p1, p2}, {1, x}, x]

{ 1.67709 - 0.0285019 x }

Then I plug in this function in my Plot

Plot[ntcrr[kelvin[t]]/(1.67709 - 0.0285019 t), {t, 30, 35}]

and that works, but I'd rather like to assign the Fit result to a function, like this:

line[x_] := Fit[{p1, p2}, {1, x}, x]
Plot[ntcrr[kelvin[t]]/line[t], {t, 30, 35}]

but that doesn't work. How can I assign a Fit result to a function?


Use Set[] (=) instead of SetDelayed[] (:=) on the output of Fit[], like so:

line[x_] = Fit[{p1, p2}, {1, x}, x];

Plot[ntcrr[kelvin[t]]/line[t], {t, 30, 35}]

Addendum by Mr. Wizard

You may wish to localize the variable in this construct, so that the creation of the definition is safe from a global assignment. Here are two ways of achieving this:

  • Block

          f[x_] = Fit[{p1, p2}, {1, x}, x]
  • Formal Symbols (looks better in a notebook):

    f[\[FormalX]_] = Fit[{p1, p2}, {1, \[FormalX]}, \[FormalX]]
  • $\begingroup$ That was almost too easy, I don't think I should upvote you for this ;-). Thanks a bunch! (I did upvote, of course) $\endgroup$ – stevenvh Jul 13 '12 at 7:48
  • $\begingroup$ No problem; though I should also probably tell you about FindFit[], which returns the parameters only instead of the function itself. It might be more convenient for you to use... $\endgroup$ – J. M.'s technical difficulties Jul 13 '12 at 7:50
  • $\begingroup$ Do you think so? I'm not really interested in the separate coefficients, just the function. With FindFit I would have to reconstruct the function myself, right? $\endgroup$ – stevenvh Jul 13 '12 at 7:53
  • $\begingroup$ Well, I said "might be"; you could, for instance, do {m, k} = {m0, k0} /. FindFit[{p1, p2}, m0 x + k0, {m0, k0}, x] and then Plot[ntcrr[kelvin[t]]/(m t + k), {t, 30, 35}]. $\endgroup$ – J. M.'s technical difficulties Jul 13 '12 at 8:01
  • $\begingroup$ Thanks for the addendum, Wizard. :) $\endgroup$ – J. M.'s technical difficulties Jul 14 '12 at 4:31

If, for any conceivable reason, you want to preserve the SetDelayed (:=), you might want to try

line2 := Function[{y}, Evaluate[Fit[{p1, p2}, {1, y}, y]]]
Plot[ntcrr[kelvin[t]]/line2[t], {t, 30, 35}, Evaluated -> True]
  • 1
    $\begingroup$ Now, try executing line2[0]. $\endgroup$ – J. M.'s technical difficulties Jul 13 '12 at 14:20
  • $\begingroup$ @J.M. Touché. Adding Evaluate should have fixed the issue, though one may wonder if there is any point in keeping the SetDelayed at this point. Not a very good answer, I reckon. $\endgroup$ – Andrea Colonna Jul 13 '12 at 14:24
  • $\begingroup$ @stevenvh On my computer (Mathematica v 8.0.1 on Win7) the code I suggested works just fine, even though J.M.'s solution is superior beyond a shadow of a doubt. $\endgroup$ – Andrea Colonna Jul 13 '12 at 15:52
  • $\begingroup$ @AndreaColonna: if you wonder about SetDelayed, why don't you just exchange it to Set (=). That works alright and is the thing to do here. With that change, I think it is a perfect way to define such a function, to some extent I like that even better than the function definition per downvalues. You should also note that the Evaluated -> True option isn't actually necessary then. $\endgroup$ – Albert Retey Apr 26 '13 at 12:26
  • $\begingroup$ @AndreaColonna: one more point: you can/should use the same techniques to localize or protect the symbols used as function arguments as in J.M.s answer, e.g.: line2=Block[{y},Function[{y}, Evaluate[Fit[{p1, p2}, {1, y}, y]]]] $\endgroup$ – Albert Retey Apr 26 '13 at 12:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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