Skip to content

How to use ifelse without invoking warnings

6 messages · John Fox, Ravi Varadhan, Avi Gross +2 more

#
Dear Ravi,

It's already been suggested that you could disable warnings, but that's 
risky in case there's a warning that you didn't anticipate. Here's a 
different approach:

 > kk <- k[k >= -1 & k <= n]
 > ans <- numeric(length(k))
 > ans[k > n] <- 1
 > ans[k >= -1 & k <= n] <- pbeta(p, kk + 1, n - kk, lower.tail=FALSE)
 > ans
[1] 0.000000000 0.006821826 0.254991551 1.000000000

BTW, I don't think that you mentioned that p = 0.3, but that seems 
apparent from the output you showed.

I hope this helps,
  John
#
Thank you to Bert, Sarah, and John. I did consider suppressing warnings, but I felt that there must be a more principled approach.  While John's solution is what I would prefer, I cannot help but wonder why `ifelse' was not constructed to avoid this behavior.

Thanks & Best regards,
Ravi
#
Dear Ravi,
On 2021-10-08 8:21 a.m., Ravi Varadhan wrote:
The conditional if () else, which works on an individual logical value, 
uses lazy evaluation and so can avoid the problem you encountered. My 
guess is that implementing lazy evaluation for the vectorized ifelse() 
would incur too high a computational overhead for large arguments.

Best,
  John
#
Ravi,

I have no idea what motivated the people who made ifelse() but there is no
reason they felt the need to program it to meet your precise need. As others
have noted, it probably was built to handle simple cases well and it expects
to return a result that is the same length as the input. If some of the
processing returns an NA or a NaN then that is what it probably should
return. 

What is the alternative? Return a shorter result? Replace it with a zero?
Fail utterly and abort the program?

YOU as the programmer should make such decisions for a non-routine case.

You can create functions with names like wrapperIf() and wrapperElse() and
do your ifelse like this:

result <- ifelse(condition, wrapperIf(args), wrapperElse(args))

Why the wrappers? If your logic is to replace NaN with 0 or NA or 666 or
Inf, then the code for it would invoke your functionality and if tested to
be a NaN it would replace it as you wish. Yes, it would slow things down a
bit but leave the ifelse() routine fairly simple.

If your goal is to remove those entries, you can do it after by manipulating
"result" above such as not keeping any item that matches 666, or even
without the wrappers, something like:

result <- result[!is.nan(result)]

But, of course, warnings are only suppressed if done right. Clearly you can
very selectively suppress warnings in the wrapper functions above without
also suppressing some other more valid warnings. But if the warning is
coming from ifelse() itself then not ever having it see a NaN would suppress
that.

Do note that the implementation of ifelse() is currently a function, not
some internal call. You can copy that and make your own slightly modified
version if you wish. 

(no R) Avi

-----Original Message-----
From: R-help <r-help-bounces at r-project.org> On Behalf Of Ravi Varadhan via
R-help
Sent: Friday, October 8, 2021 8:22 AMiu
To: John Fox <jfox at mcmaster.ca>l
Cc: R-Help <r-help at r-project.org>
Subject: Re: [R] How to use ifelse without invoking warnings

Thank you to Bert, Sarah, and John. I did consider suppressing warnings, but
I felt that there must be a more principled approach.  While John's solution
is what I would prefer, I cannot help but wonder why `ifelse' was not
constructed to avoid this behavior.

Thanks & Best regards,
Ravi
#
I don't think it is avoidable... ifelse cannot figure out which elements will exist in the second and third arguments until they are evaluated, so it cannot make use of the TRUE/FALSE information until both possible output vectors have been evaluated, which is a performance hit and yields warnings or errors.

You, on the other hand, can figure that out and use input validation to limit which inputs get fed into the warning- or error- producing algorithm and put the results into a final result vector using indexed assignment as Dr Fox suggested.
On October 8, 2021 5:21:44 AM PDT, Ravi Varadhan via R-help <r-help at r-project.org> wrote:

  
    
#
On Sat, Oct 9, 2021 at 3:00 AM Ravi Varadhan via R-help
<r-help at r-project.org> wrote:
Note that John's approach is mentioned twice in the help page for
ifelse, once in the examples, and once quite early on in the "Warning"
section:

     Sometimes it is better to use a construction such as

       (tmp <- yes; tmp[!test] <- no[!test]; tmp)

     , possibly extended to handle missing values in 'test'.

Best,
-Deepayan