# How can I assign a Fit result to a function?

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]}; p2 = {35, ntcrr[kelvin]};
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?

## 2 Answers

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

Block[{x},
f[x_] = Fit[{p1, p2}, {1, x}, x]
]

• Formal Symbols (looks better in a notebook):

f[\[FormalX]_] = Fit[{p1, p2}, {1, \[FormalX]}, \[FormalX]]

• That was almost too easy, I don't think I should upvote you for this ;-). Thanks a bunch! (I did upvote, of course) – stevenvh Jul 13 '12 at 7:48
• 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... – J. M. is away Jul 13 '12 at 7:50
• 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? – stevenvh Jul 13 '12 at 7:53
• 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}]. – J. M. is away Jul 13 '12 at 8:01
• Thanks for the addendum, Wizard. :) – J. M. is away 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]

• Now, try executing line2. – J. M. is away Jul 13 '12 at 14:20
• @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. – Andrea Colonna Jul 13 '12 at 14:24
• @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. – Andrea Colonna Jul 13 '12 at 15:52
• @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. – Albert Retey Apr 26 '13 at 12:26
• @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]]]] – Albert Retey Apr 26 '13 at 12:28