diff --git a/R/DESCRIPTION b/R/DESCRIPTION index 637e88f72..43cd8c2ea 100644 --- a/R/DESCRIPTION +++ b/R/DESCRIPTION @@ -1,7 +1,7 @@ Package: Robyn Type: Package Title: Semi-Automated Marketing Mix Modeling (MMM) from Meta Marketing Science -Version: 3.10.5.9014 +Version: 3.10.5.9015 Authors@R: c( person("Gufeng", "Zhou", , "gufeng@meta.com", c("cre","aut")), person("Leonel", "Sentana", , "leonelsentana@meta.com", c("aut")), diff --git a/R/R/auxiliary.R b/R/R/auxiliary.R index 847de5174..c4c53ccea 100644 --- a/R/R/auxiliary.R +++ b/R/R/auxiliary.R @@ -78,7 +78,7 @@ baseline_vars <- function(InputCollect, baseline_level) { stopifnot(baseline_level %in% 0:5) x <- "" if (baseline_level >= 1) - x <- c(x, "(Intercept)") + x <- c(x, "(Intercept)", "intercept") if (baseline_level >= 2) x <- c(x, "trend") if (baseline_level >= 3) diff --git a/R/R/plots.R b/R/R/plots.R index 138d73164..e6f9e68d2 100644 --- a/R/R/plots.R +++ b/R/R/plots.R @@ -1485,8 +1485,13 @@ ts_validation <- function(OutputModels, quiet = FALSE, ...) { #' @param solID Character vector. Model IDs to plot. #' @param exclude Character vector. Manually exclude variables from plot. #' @export -decomp_plot <- function(InputCollect, OutputCollect, solID = NULL, exclude = NULL) { +decomp_plot <- function( + InputCollect, OutputCollect, solID = NULL, + exclude = NULL, baseline_level = 0) { + if (is.null(solID) && length(OutputCollect$allSolutions) == 1) + solID <- OutputCollect$allSolutions check_opts(solID, OutputCollect$allSolutions) + bvars <- baseline_vars(InputCollect, baseline_level) intType <- str_to_title(case_when( InputCollect$intervalType %in% c("month", "week") ~ paste0(InputCollect$intervalType, "ly"), InputCollect$intervalType == "day" ~ "daily", @@ -1501,7 +1506,14 @@ decomp_plot <- function(InputCollect, OutputCollect, solID = NULL, exclude = NUL ) %>% tidyr::gather("variable", "value", -.data$ds, -.data$solID, -.data$dep_var) %>% filter(!.data$variable %in% exclude) %>% - mutate(variable = factor(.data$variable, levels = rev(unique(.data$variable)))) + mutate(variable = ifelse( + .data$variable %in% bvars, paste0("Baseline_L", baseline_level), as.character(.data$variable))) %>% + group_by(.data$solID, .data$ds, .data$variable) %>% + summarise(value = sum(.data$value, na.rm = TRUE), + value = sum(.data$value, na.rm = TRUE), + .groups = "drop") %>% + arrange(abs(.data$value)) %>% + mutate(variable = factor(.data$variable, levels = unique(.data$variable))) p <- ggplot(df, aes(x = .data$ds, y = .data$value, fill = .data$variable)) + facet_grid(.data$solID ~ .) + labs( diff --git a/R/R/response.R b/R/R/response.R index f9f636d70..7334a7ba0 100644 --- a/R/R/response.R +++ b/R/R/response.R @@ -23,56 +23,83 @@ #' @examples #' \dontrun{ #' # Having InputCollect and OutputCollect objects +#' ## Recreate original saturation curve +#' Response <- robyn_response( +#' InputCollect = InputCollect, +#' OutputCollect = OutputCollect, +#' select_model = select_model, +#' metric_name = "facebook_S" +#' ) +#' Response$plot #' -#' # Get marginal response (mResponse) and marginal ROI (mROI) for -#' # the next 1k on 80k for search_S -#' spend1 <- 80000 +#' ## Or you can call a JSON file directly (a bit slower) +#' # Response <- robyn_response( +#' # json_file = "your_json_path.json", +#' # dt_input = dt_simulated_weekly, +#' # dt_holidays = dt_prophet_holidays, +#' # metric_name = "facebook_S" +#' # ) +#' +#' ## Get the "next 100 dollar" marginal response on Spend1 +#' Spend1 <- 20000 #' Response1 <- robyn_response( #' InputCollect = InputCollect, #' OutputCollect = OutputCollect, -#' metric_name = "search_S", -#' metric_value = spend1 -#' )$response -#' # Get ROI for 80k -#' Response1 / spend1 # ROI for search 80k +#' select_model = select_model, +#' metric_name = "facebook_S", +#' metric_value = Spend1, # total budget for date_range +#' date_range = "last_1" # last two periods +#' ) +#' Response1$plot #' -#' # Get response for 81k -#' spend2 <- spend1 + 1000 +#' Spend2 <- Spend1 + 100 #' Response2 <- robyn_response( #' InputCollect = InputCollect, #' OutputCollect = OutputCollect, -#' metric_name = "search_S", -#' metric_value = spend2 -#' )$response +#' select_model = select_model, +#' metric_name = "facebook_S", +#' metric_value = Spend2, +#' date_range = "last_1" +#' ) +#' # ROAS for the 100$ from Spend1 level +#' (Response2$response_total - Response1$response_total) / (Spend2 - Spend1) #' -#' # Get ROI for 81k -#' Response2 / spend2 # ROI for search 81k -#' # Get marginal response (mResponse) for the next 1k on 80k -#' Response2 - Response1 -#' # Get marginal ROI (mROI) for the next 1k on 80k -#' (Response2 - Response1) / (spend2 - spend1) +#' ## Get response from for a given budget and date_range +#' Spend3 <- 100000 +#' Response3 <- robyn_response( +#' InputCollect = InputCollect, +#' OutputCollect = OutputCollect, +#' select_model = select_model, +#' metric_name = "facebook_S", +#' metric_value = Spend3, # total budget for date_range +#' date_range = "last_5" # last 5 periods +#' ) +#' Response3$plot #' -#' # Example of getting paid media exposure response curves -#' imps <- 1000000 +#' ## Example of getting paid media exposure response curves +#' imps <- 10000000 #' response_imps <- robyn_response( #' InputCollect = InputCollect, #' OutputCollect = OutputCollect, +#' select_model = select_model, #' metric_name = "facebook_I", #' metric_value = imps -#' )$response -#' response_per_1k_imps <- response_imps / imps * 1000 -#' response_per_1k_imps +#' ) +#' response_imps$response_total / imps * 1000 +#' response_imps$plot #' -#' # Get response for 80k for search_S from the a certain model SolID -#' # in the current model output in the global environment -#' robyn_response( +#' ## Example of getting organic media exposure response curves +#' sendings <- 30000 +#' response_sending <- robyn_response( #' InputCollect = InputCollect, #' OutputCollect = OutputCollect, -#' metric_name = "search_S", -#' metric_value = 80000, -#' dt_hyppar = OutputCollect$resultHypParam, -#' dt_coef = OutputCollect$xDecompAgg +#' select_model = select_model, +#' metric_name = "newsletter", +#' metric_value = sendings #' ) +#' # response per 1000 sendings +#' response_sending$response_total / sendings * 1000 +#' response_sending$plot #' } #' @return List. Response value and plot. Class: \code{robyn_response}. #' @export diff --git a/R/man/robyn_outputs.Rd b/R/man/robyn_outputs.Rd index 8c8312b45..652854da3 100644 --- a/R/man/robyn_outputs.Rd +++ b/R/man/robyn_outputs.Rd @@ -60,7 +60,13 @@ robyn_onepagers( ts_validation(OutputModels, quiet = FALSE, ...) -decomp_plot(InputCollect, OutputCollect, solID = NULL, exclude = NULL) +decomp_plot( + InputCollect, + OutputCollect, + solID = NULL, + exclude = NULL, + baseline_level = 0 +) } \arguments{ \item{InputCollect, OutputModels}{\code{robyn_inputs()} and \code{robyn_run()} diff --git a/R/man/robyn_response.Rd b/R/man/robyn_response.Rd index 71abcb4f7..c1fa0cf45 100644 --- a/R/man/robyn_response.Rd +++ b/R/man/robyn_response.Rd @@ -75,55 +75,82 @@ result and selected model build (initial model, refresh model, etc.). \examples{ \dontrun{ # Having InputCollect and OutputCollect objects - -# Get marginal response (mResponse) and marginal ROI (mROI) for -# the next 1k on 80k for search_S -spend1 <- 80000 +## Recreate original saturation curve +Response <- robyn_response( + InputCollect = InputCollect, + OutputCollect = OutputCollect, + select_model = select_model, + metric_name = "facebook_S" +) +Response$plot + +## Or you can call a JSON file directly (a bit slower) +# Response <- robyn_response( +# json_file = "your_json_path.json", +# dt_input = dt_simulated_weekly, +# dt_holidays = dt_prophet_holidays, +# metric_name = "facebook_S" +# ) + +## Get the "next 100 dollar" marginal response on Spend1 +Spend1 <- 20000 Response1 <- robyn_response( InputCollect = InputCollect, OutputCollect = OutputCollect, - metric_name = "search_S", - metric_value = spend1 -)$response -# Get ROI for 80k -Response1 / spend1 # ROI for search 80k - -# Get response for 81k -spend2 <- spend1 + 1000 + select_model = select_model, + metric_name = "facebook_S", + metric_value = Spend1, # total budget for date_range + date_range = "last_1" # last two periods +) +Response1$plot + +Spend2 <- Spend1 + 100 Response2 <- robyn_response( InputCollect = InputCollect, OutputCollect = OutputCollect, - metric_name = "search_S", - metric_value = spend2 -)$response - -# Get ROI for 81k -Response2 / spend2 # ROI for search 81k -# Get marginal response (mResponse) for the next 1k on 80k -Response2 - Response1 -# Get marginal ROI (mROI) for the next 1k on 80k -(Response2 - Response1) / (spend2 - spend1) - -# Example of getting paid media exposure response curves -imps <- 1000000 + select_model = select_model, + metric_name = "facebook_S", + metric_value = Spend2, + date_range = "last_1" +) +# ROAS for the 100$ from Spend1 level +(Response2$response_total - Response1$response_total) / (Spend2 - Spend1) + +## Get response from for a given budget and date_range +Spend3 <- 100000 +Response3 <- robyn_response( + InputCollect = InputCollect, + OutputCollect = OutputCollect, + select_model = select_model, + metric_name = "facebook_S", + metric_value = Spend3, # total budget for date_range + date_range = "last_5" # last 5 periods +) +Response3$plot + +## Example of getting paid media exposure response curves +imps <- 10000000 response_imps <- robyn_response( InputCollect = InputCollect, OutputCollect = OutputCollect, + select_model = select_model, metric_name = "facebook_I", metric_value = imps -)$response -response_per_1k_imps <- response_imps / imps * 1000 -response_per_1k_imps +) +response_imps$response_total / imps * 1000 +response_imps$plot -# Get response for 80k for search_S from the a certain model SolID -# in the current model output in the global environment -robyn_response( +## Example of getting organic media exposure response curves +sendings <- 30000 +response_sending <- robyn_response( InputCollect = InputCollect, OutputCollect = OutputCollect, - metric_name = "search_S", - metric_value = 80000, - dt_hyppar = OutputCollect$resultHypParam, - dt_coef = OutputCollect$xDecompAgg + select_model = select_model, + metric_name = "newsletter", + metric_value = sendings ) +# response per 1000 sendings +response_sending$response_total / sendings * 1000 +response_sending$plot } }