Efficient date-based lookup function in R Right now this function takes an excessively long time to run, please let me know how to make it more efficient.

lunarCal is 144x7 and the dput for it is here.

Here's the code:

if(!require(pacman)) install.packages("pacman")
pacman::p_load(lubridate)
cat("Please make sure that birthday inputs are in YYYY-MM-DD format")

lunarCal             &lt;- readRDS("data/lunarCal.RDS")

eastern.profile &lt;- function(birthday){
    good                 &lt;- is.na.POSIXlt(birthday)
    if(!(good)){birthday &lt;- strptime(birthday, format = "%Y-%m-%d", tz = "Asia/Chongqing")}
    ind                  &lt;- (lunarCal$START_DATE &lt;= birthday) &amp; (lunarCal$END_DATE &gt;= birthday)
    temp                 &lt;- subset(lunarCal, ind)
    return(temp)
}


Here's an example of its non-vectorized usage:

eastern.profile("1975-01-01")
   YEAR START_DATE   END_DATE ANIMAL ELEMENT ASPECT                                   PERSONALITY
75 1974 1974-01-23 1975-02-10  Tiger    Wood      + Imagination, creativity, idealism, compassion


When I run it I'm using sapply but it's still slow. I've got a data set with 250,000 dates I'm applying it to and it took over 15 minutes.
We can simulate the data set to run this function on with 

dat &lt;- as.data.frame(seq(as.Date("1900/1/1"), as.Date("2040/1/1"), "days"))
dat &lt;- rbind(dat,dat,dat,dat)
Have a look at the function findInterval. It is vectorized so it can treat all your dates in a single (fast) call. Your code should look something like this:

eastern.profile &lt;- function(birthday) {
   bad &lt;- !is.na.POSIXlt(birthday)
   birthday[bad] &lt;- strptime(birthday[bad], format = "%Y-%m-%d", tz = "Asia/Chongqing")
   ind &lt;- findInterval(birthday, lunarCal$START_DATE)
   cbind(birthday = birthday, lunarCal[ind, ])
}


Note that I was not able to test because of some issues I had with your data. So it may need some tweaks.