[R] FW: NaN from function
(Ted Harding)
Ted.Harding at wlandres.net
Thu Feb 23 17:40:07 CET 2012
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.Harding at wlandres.net>
Date: 23-Feb-2012 Time: 16:40:03
This message was sent by XFMail
More information about the R-help
mailing list