Search code examples
rfor-loopforecastingfacebook-prophet

Prophet Forecasting using R for multiple items


I am very new to time series forecasting using Prophet in R. I am able to predict values for one single product using Prophet. Is there any way if i can use loop to generate forecast using Prophet for multiple products? The below code works absolutely fine for single product but i am trying to generate forecasts for multiple products

 library(prophet)
 df <- read.csv("Prophet.csv")
 df$Date<-as.Date(as.character(df$Date), format =  "%d-%m-%Y")
 colnames(df) <- c("ds", "y")
 m <- prophet(df)
 future <- make_future_dataframe(m, periods = 40)
 tail(future)
 forecast <- predict(m, future)
 write.csv(forecast[c('ds','yhat')],"Output_Prophet.csv")
 tail(forecast[c('ds', 'yhat', 'yhat_lower', 'yhat_upper')])

Sample Dataset:

enter image description here


Solution

  • This can be done by using lists and map functions from the purrr package.

    Lets build some data:

    library(tidyverse) # contains also the purrr package
    set.seed(123)
    tb1 <- tibble(
      ds = seq(as.Date("2018-01-01"), as.Date("2018-12-31"), by = "day"),
      y = sample(365)
    )
    tb2 <- tibble(
      ds = seq(as.Date("2018-01-01"), as.Date("2018-12-31"), by = "day"),
      y = sample(365)
    )
    
    ts_list <- list(tb1, tb2) # two separate time series
    # using this construct you could add more of course
    

    Build and prediction:

    library(prophet)
    
    m_list <- map(ts_list, prophet) # prophet call
    
    future_list <- map(m_list, make_future_dataframe, periods = 40) # makes future obs
    
    forecast_list <- map2(m_list, future_list, predict) # map2 because we have two inputs
    
    # we can access everything we need like with any list object
    head(forecast_list[[1]]$yhat) # forecasts for time series 1
    [1] 179.5214 198.2375 182.7478 173.5096 163.1173 214.7773
    head(forecast_list[[2]]$yhat) # forecast for time series 2
    [1] 172.5096 155.8796 184.4423 133.0349 169.7688 135.2990
    

    Update (just the input part, build and prediction part it's the same):

    I created a new example based on OP request, basically you need to put everything again in a list object:

    # suppose you have a data frame like this:
    set.seed(123)
    tb1 <- tibble(
      ds = seq(as.Date("2018-01-01"), as.Date("2018-12-31"), by = "day"),
      productA = sample(365),
      productB = sample(365)
    )
    head(tb1)
    # A tibble: 6 x 3
      ds         productA productB
      <date>        <int>    <int>
    1 2018-01-01      105      287
    2 2018-01-02      287       71
    3 2018-01-03      149        7
    4 2018-01-04      320      148
    5 2018-01-05      340      175
    6 2018-01-06       17      152
    
    # with some dplyr and base R you can trasform each time series in a data frame within a list
    ts_list <- tb1 %>% 
      gather("type", "y", -ds) %>% 
      split(.$type)
    # this just removes the type column that we don't need anymore
    ts_list <- lapply(ts_list, function(x) { x["type"] <- NULL; x })
    
    # now you can continue just like above..