Avoid warnings from FALSE part of ifelse()

Viewed 419

I created a user function that computes Hedges' c() bias correction for g (Hedges, 1981). It is directly based on metafor::.cmicalc() function from library(metafor). It does this:

hedges_c <- function(df) {
  return(exp(lgamma(df / 2) - log(sqrt(df / 2)) - lgamma((df - 1)/2)))
}

When applied to a vector containing values <= 1, lgamma() generates a warning, because lgamma(0) (as well as any negative value) generates NaN. So, my solution (and also what metafor::.cmicalc() does) was including an ifelse() statement:

hedges_c <- function(df) {
  cdf <- ifelse(df <= 1, 
                NA,
                exp(lgamma(df / 2) - log(sqrt(df / 2)) - lgamma((df - 1)/2)))
  return(cdf)
}

But, and here is the problem I don't seem to find the solution to, it still generates the warnings(), even if all the values are correctly rendered as NA.

Example:

hedges_c(c(0, 0, 20, 14, 0, 0, 0, 0))
#[1]      NA      NA 0.9619445 0.9452877      NA      NA      NA      NA
#Warning messages:
#1: In ifelse(df <= 1, NA, exp(lgamma(df/2) - log(sqrt(df/2)) - lgamma((df -  :
#  value out of range in 'lgamma'
#(...)

I understand (e.g., from this answer) that the third (FALSE) argument of ifelse() is evaluated even when the condition is TRUE (and inversely if I change the order of the condition and the arguments)... But I simply don't know how to solve that (except maybe for hiding warnings before and after...).

(Note: I also tried dplyr::case_when(), but it is exactly the same problem.)

2 Answers

I'm pretty sure the values are calculated regardless, and just subset out by ifelse. You could always just apply your function to the valid values and make the rest NA:

hedges_c <- function(df) {
  ss <- df >= 1

  hc <- function(x) exp(lgamma(x / 2) - log(sqrt(x / 2)) - lgamma((x - 1)/2))

  df[ss]  <- hc(df[ss])
  df[!ss] <- NA
  df
}

hedges_c(c(0, 0, 20, 14, 0, 0, 0, 0))
#[1]        NA        NA 0.9619445 0.9452877        NA        NA        NA        NA

Try using a different approach. Something like the following.

hedges_c <- function(df) {
  cdf <- rep(NA, length(df))
  inx <- df > 1
  cdf[inx] <- exp(lgamma(df[inx] / 2) - log(sqrt(df[inx] / 2)) - lgamma((df[inx] - 1)/2))
  return(cdf)
}

hedges_c(c(0, 0, 20, 14, 0, 0, 0, 0))
#[1]        NA        NA 0.9619445 0.9452877        NA        NA        NA
#[8]        NA

And the warnings are gone.

Related