/************** BOX-COX ************************ Author: Marc Nerlove AREC/2200 Symons Hall University of Maryland College Park, Maryland 20742-5535 301-405-1388 FAX: 301-314-9032 mnerlove@arec.umd.edu http://www.arec.umd.edu/mnerlove/mnerlove Submitted: Nov 1998 Code provided gratis without performance guarantees for public non-commercial use. ***********************************************************/ /*GENERAL PROCEDURE FOR THE BOX-COX TRANSFORM.*/ /*There is a serious problem with the Box-Cox transform near zero on a finite precision computer. The problem is that in the expression (x^a - 1)/a, x>0, a<1, x^a reaches its limit of precision before the limit of precision of division by a. This produces what I have called a dorsal finned likelihood function in the case of the wine data where the parameter crosses zero. It causes failure to converge in the GAUSS library CML and problems with grid search as well. A naive replacement of the transform by LN( ) at zero simply will not work satisfactorily.*/ /*zz is any N by 1 vector. lambda is the Box-Cox parameter.*/ proc boxcox( zz, lambda ); local zbc; if abs(lambda) .LE 1e-8; zbc = ln(abs(zz)); else; zbc = ((zz^lambda)-1) ./ lambda; endif; retp(zbc); endp; /*********************End Box-Cox Procedure**********************/ /***************** supplementary code ************************* author: anonymous date: 2 Nov 98 Code provided gratis without performance guarantees for public non-commercial use. The naive calculation of the Box-Cox function, as Professor Nerlove has pointed out in a separate post, fails for lambda < 1e-8. This might not seem to be much of a problem, but it can play havoc with the calculation of numerical derivatives when estimating models that include the Box-Cox function using Maxlik or CML. Professor Nerlove's solution, truncating the calculation at 1e-8, is problematic as well for calculating numerical derivatives because it creates a discontinuity at 1e-8 and -1e-8. I recommend the procedure below. It is accurate to 14 places or so for any value of lambda. **************************************************************/ proc boxcox(x,lambda); for i(1,rows(x),1); for j(1,cols(x),1); x[i,j] = boxcox0(x[i,j],lambda); endfor; endfor; endp; proc boxcox0( x, lambda ); local a, b, result; if x == 1; retp(0); endif; if lambda > 1 or lambda < -1; retp( (exp(lambda*ln(x)) - 1) / lambda ); elseif lambda == 1; retp( x - 1 ); elseif lambda == 0; retp( ln(x) ); else; a = ln(x); b = lambda * a; result = a; for i(2,100,1); a = a * b / i; if a == 0; break; endif; result = result + a; endfor; retp(result); endif; endp;