Search code examples
rtidyverselubridate

Applying a calendar function directly into a tibble


Is a way to apply create_calendar directly into a tibble? I found a work around which is to create a "Calendar" df based off the other data set Calendar <- create_calendar(df$Date) and then bind the columns together df <- left_join(df, Calendar, by = "Date") but would like to understand how to apply it directly into a df.

Thanks!

Current approach:

#Create Calendar Function
create_calendar = function(dates) {

#Create a sequence of dates from the minimum to the maximum date in the input column
  Dates = seq(min(dates), max(dates), by="days")
  
#Convert the dates to a tibble and add additional columns
  Calendar = as_tibble(Dates) %>%
    rename(Date = value) %>%
    mutate(
      DateNo = day(Date),
      NameDay = wday(Date,label = TRUE, abbr=FALSE),
      NameDayShort = wday(Date,label = TRUE),
      DayinWeek = wday(Date),
      MonthNo = month(Date),
      NameMonth = month(Date, label = TRUE, abbr=FALSE),
      NameMonthShort = month(Date, label = TRUE),
      Week = week(Date),
      Year = year(Date),
      Quarter = quarter(Date, with_year = F, fiscal_start = 7)) %>% 

#Month number for the Australian financial year
  Calendar <- Calendar %>%
    mutate(AFYMonth = case_when(
      NameMonthShort == "Jul" ~ 1
      NameMonthShort == "Aug" ~ 2,
      NameMonthShort == "Sep" ~ 3,
      NameMonthShort == "Oct" ~ 4,
      NameMonthShort == "Nov" ~ 5,
      NameMonthShort == "Dec" ~ 6,
      NameMonthShort == "Jan" ~ 7,
      NameMonthShort == "Feb" ~ 8,
      NameMonthShort == "Mar" ~ 9,
      NameMonthShort == "Apr" ~ 10,
      NameMonthShort == "May" ~ 11,
      NameMonthShort == "Jun" ~ 12,
    ))
  
#Format the week column as %V
  Calendar$Week <- format(Calendar$Date, format = "%V")
  
  return(Calendar)
}

#Read function and apply to current df [Missing Step]
df <- df %>%
  mutate(Calendar = create_calendar(Date))

Solution

  • Yes, you can the tidyverse operator {{}}, it allows to reference a column name inside a tidyverse function.

    Function

    library(lubridate)
    library(dplyr)
    
    
    create_calendar <- function(df,dt_var) {
      
    
      #Convert the dates to a tibble and add additional columns
      Calendar <-
        df %>% 
        mutate(
          DateNo = day({{dt_var}}),
          NameDay = wday({{dt_var}},label = TRUE, abbr=FALSE),
          NameDayShort = wday({{dt_var}},label = TRUE),
          DayinWeek = wday({{dt_var}}),
          MonthNo = month({{dt_var}}),
          NameMonth = month({{dt_var}}, label = TRUE, abbr=FALSE),
          NameMonthShort = month({{dt_var}}, label = TRUE),
          Week = week({{dt_var}}),
          Year = year({{dt_var}}),
          Quarter = quarter({{dt_var}}, with_year = F, fiscal_start = 7)) 
        
        #Month number for the Australian financial year
        Calendar <- 
          Calendar %>%
          mutate(AFYMonth = case_when(
            NameMonthShort == "Aug" ~ 1,
            NameMonthShort == "Sep" ~ 2,
            NameMonthShort == "Oct" ~ 3,
            NameMonthShort == "Nov" ~ 4,
            NameMonthShort == "Dec" ~ 5,
            NameMonthShort == "Jan" ~ 6,
            NameMonthShort == "Feb" ~ 7,
            NameMonthShort == "Mar" ~ 8,
            NameMonthShort == "Apr" ~ 9,
            NameMonthShort == "May" ~ 10,
            NameMonthShort == "Jun" ~ 11,
            NameMonthShort == "Jul" ~ 12
          ))
        
        #Format the week column as %V
        Calendar$Week <- format(Calendar$Date, format = "%V")
        
        return(Calendar)
    }
    

    Example

    df <- data.frame(dt = lubridate::dmy("01/01/01"))
    
    create_calendar(df,dt)