6
$\begingroup$

I'm trying to use Manipulate to visually try out different values of lambda in a Box-Cox transformation. I've created a boxcox function with two definitions to deal with both the normal case and the case when lambda is 0:

boxcox[data_, 0] := Log[data]
boxcox[data_, l_] := (data^l - 1)/l

Then I use this function inside Manipulate but I keep getting tons of errors. It looks like Manipulate is only using the general definition and starts complaining about dividing by zero.

Manipulate[
 pdata = Partition[boxcox[data, u], 12];
 ranges = Max[#] - Min[#] & /@ pdata;
 means = Mean[#] & /@ pdata;
 mrdata = Transpose[{means, ranges}];
 mrlm = LinearModelFit[mrdata, x, x];
 Show[
  ListPlot[mrdata, Axes -> False, Frame -> True, 
   AxesOrigin -> {Automatic, 0}],
  Plot[mrlm[x], {x, Min[means], Max[means]}]
  ],
 {u, 0.00, 1.00}
 ]

Here is the data I'm using in case it matters:

data = {154., 96., 73., 49., 36., 59., 95., 169., 210., 278., 298., 245., \
200., 118., 90., 79., 78., 91., 167., 169., 289., 347., 375., 203., \
223., 104., 107., 85., 75., 99., 135., 211., 335., 460., 488., 326., \
346., 261., 224., 141., 148., 145., 223., 272., 445., 560., 612., \
467., 518., 404., 300., 210., 196., 186., 247., 343., 464., 680., \
711., 610., 613., 392., 273., 322., 189., 257., 324., 404., 677., \
858., 895., 664., 628., 308., 324., 248., 272.}
$\endgroup$
7
$\begingroup$

As already explained: MatchQ[0, 0.] is False.

Generally, I suggest using:

boxcox[data_, x_ /; x == 0] := Log[data]

This works even for expression that are not expressly 0 or 0., e.g.:

MatchQ[E^(I Pi/4) - (-1)^(1/4), x_ /; x == 0]
True

It also works in cases like this:

MatchQ[0.0000000000000000000, x_ /; x == 0]
True

Compare:

MatchQ[0.0000000000000000000, 0 | 0.]
False
$\endgroup$
6
$\begingroup$

You have only defined your function for 0, which is different from 0.

Head /@ {0, 0.}
(* {Integer, Real} *)

So the function is strictly defined only for an exact value of 0 with the head Integer. However, when you use it in Manipulate, the value being passed to it is a machine precision number with the head Real, and hence it uses the latter definition, since you haven't special-cased it.

To avoid it, redefine the first definition for your function as:

boxcox[data_, 0 | 0.] := Log[data]
$\endgroup$
4
$\begingroup$

Since u is a floating point number it never matches an integer zero (as a pattern).

This works as expected:

boxcox[data_, 0.] := Log[data] 

Another solution would be to define your function like this:

boxcox[data_, l_] := If[l == 0, Log[data], (data^l - 1)/l]
$\endgroup$

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.