0

I am trying to apply a function from a package to certain columns of my dataframe. The package is linked here.

However, the author of the package used simple if statements, which won't let me use apply function, because of vectorized conditions. My problem is fixing this function specifically, so that I can use it in an apply function.

Mainly there are 4 if statements that need addressing:

1:

if (month < 1 | month > 12)
    stop("month is outside the range 1-12")
  if (day < 1 | day > 31)
    stop("day is outside the range 1-31")

2:

    if (month < 7)
      {
        days <- days + 31 * (month -1 )
      } else{
        days <- days + 186 + 30 * (month - 7)
      }

3:

if (days > 36524)
  {
    days <- days - 1
    gyear <- gyear + 100 * (days %/% 36524)
    days <- days %% 36524
    if (days >= 365)
      days <- days + 1
  }

4:

  if (days > 365)
  {
    gyear <- gyear + ((days - 1) %/% 365)
    days <- (days - 1) %% 365
  }

Now I know I can fix some of them with simple ifelse statements, but I have seen people avoiding assigning variables inside an ifelse statement and I prefer to use a general approach to fix this. Also, dplyr's case_when cannot be generally applied as well. Can anyone kindly help me solve this problem in a general relatively efficient way?

edit- As per MrFlick's comment, this is how I intend to use the function I have the original dates in my dataframe in months (summed as total months)

convert_date_to_greg <- function(x){
  year = floor(as.numeric(x)/12)
  month = (as.numeric(x)%%12)+1
  day = 1 
  ifelse(is.na(x)==FALSE,return(jal2greg(year,month,day,asDate = T)),return(NA))
}

greg_convert <- lapply(date_sorted_df[,date_column_indices],
                   FUN=convert_date_to_greg)

This is a sample input:

df<- data.frame(date_1=c(16735,16234,17123,16123), date_2=c(16352,16352,16666,17124))

However, using apply, I will see the following error message:

the condition has length > 1

  • Maybe just try wrapping the function in `Vectorize()`? It's unclear exactly how you want to call this function. It's easier to help you if you provide a [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) with sample input and desired output that can be used to test and verify possible solutions. – MrFlick May 25 '22 at 17:13
  • Thank you for your reply. As per your comment, how I intend to use it and a sample is provided. @MrFlick – The_old_man May 25 '22 at 17:27

1 Answers1

1

apply() type functions are for vectorized functions; they are not meant to be used with functions like this. You'll probably need to fix the function or use a solution other than apply().

I'd suggest fixing the function (R code should be vectorized when possible). For 1, you'll just want to check if any inputs are invalid. For 2-4, ifelse() will be helpful.

For 1:

if (sum(month < 1 | month > 12) != 0) { stop("a month is outside the range 1-12") }
if (sum(day < 1 | day > 31) != 0) { stop("a day is outside the range 1-31") }

For 2:

days <- ifelse(month < 7, days + 31 * (month -1 ), days + 186 + 30 * (month - 7))

For 3:

days <- days - 1
gyear <- gyear + 100 * (days %/% 36524)
days <- days %% 36524
days <- ifelse(days >= 365, days <- days + 1, days)     

For 4:

gyear <- ifelse(days > 365, gyear + ((days - 1) %/% 365, gyear)
days  <- ifelse(days > 365, (days - 1) %% 365, days)
Thomas Rosa
  • 630
  • 10
  • 21
  • Thank you so much for your answer, I apologize as I mis-copied the code in section 3 and missed the if statement at the top, however, I think I got the gist of it. Thanks again. – The_old_man May 25 '22 at 17:36