On 23-Feb-2012 Jonathan Williams wrote: > Dear Helpers, > I wrote a simple function to standardise variables if they > contain more than one value. If the elements of the variable > are all identical, then I want the function to return zero. > > When I submit variables whose elements are all identical to > the function, it returns not zero, but NaNs. > > zt=function(x){if (length(table(x)>1)) y=(x-mean(x))/sd(x) else if > (length(table(x)==1)) y=0; return(y)} > > zt(c(1:10)) >#[1] -1.4863011 -1.1560120 -0.8257228 -0.4954337 -0.1651446 0.1651446 >#0.4954337 0.8257228 1.1560120 1.4863011 > > zt(rep(1,10)) >#[1] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN > > Would you be so kind as to point out what I am doing wrong, here? > How can I obtain zeros from my function, instead of NaNs? > (I obtain NaNs also if I set the function to zt=function(x){ > if (length(table(x)>1)) y=(x-mean(x))/sd(x) else if > (length(table(x)==1)) y=rep(0, length(x)); return(y)} ). > > Thanks, in advance, for your help, > Jonathan Williams
The issue here, Jonathan, is that when you evaluate (x-mean(x))/sd(x) for a vector x whose elements are all equal, not only is (x-mean(x)) = 0, but also sd(x) = 0, so you are asking the function to return the result of 0/0. Since this is undefined, the result is NaN. A basic solution for this special case would be zt=function(x){ if (sd(x) == 0) return(0*x) else return( (x-mean(x))/sd(x) ) } This should cover the case where length(table(x))==1 (see also below). I'm not happy about your conditions if (length(table(x)>1)) if (length(table(x)==1)) since they ask for "length(table(x)>1)", which doesn't seem to represent any natural criterion. E.g.: length(table(1:10)>1) # [1] 10 length(table(rep(1,10))>1) # [1] 1 if(length(table(1:10)>1)) y <- "Yes" else y <- "No" ; y # [1] "Yes" if(length(table(rep(1,10))>1)) y <- "Yes" else y <- "No" ; y # [1] "Yes" length(table(1:10)==1) # [1] 10 length(table(rep(1,10))==1) # [1] 1 if(length(table(1:10)==1)) y <- "Yes" else y <- "No" ; y # [1] "Yes" if(length(table(rep(1,10))==1)) y <- "Yes" else y <- "No" ; y # [1] "Yes" I suspect you meant to write if (length(table(x))>1) and if (length(table(x)))==1) since this distinguishes between two more more different values (length(table(x)) > 1) and all equal values (length(table(x)) == 1). Ted. ------------------------------------------------- E-Mail: (Ted Harding) <ted.hard...@wlandres.net> Date: 23-Feb-2012 Time: 16:40:03 This message was sent by XFMail ______________________________________________ R-help@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.