Skip to content

Commit 71a949c

Browse files
feat: enable baseline_level param and NULL solID for decomp_plot() + docs: update robyn_response() examples (#923)
1 parent dcd3f47 commit 71a949c

File tree

6 files changed

+143
-71
lines changed

6 files changed

+143
-71
lines changed

R/DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: Robyn
22
Type: Package
33
Title: Semi-Automated Marketing Mix Modeling (MMM) from Meta Marketing Science
4-
Version: 3.10.5.9014
4+
Version: 3.10.5.9015
55
Authors@R: c(
66
person("Gufeng", "Zhou", , "gufeng@meta.com", c("cre","aut")),
77
person("Leonel", "Sentana", , "leonelsentana@meta.com", c("aut")),

R/R/auxiliary.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ baseline_vars <- function(InputCollect, baseline_level) {
7878
stopifnot(baseline_level %in% 0:5)
7979
x <- ""
8080
if (baseline_level >= 1)
81-
x <- c(x, "(Intercept)")
81+
x <- c(x, "(Intercept)", "intercept")
8282
if (baseline_level >= 2)
8383
x <- c(x, "trend")
8484
if (baseline_level >= 3)

R/R/plots.R

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,8 +1485,13 @@ ts_validation <- function(OutputModels, quiet = FALSE, ...) {
14851485
#' @param solID Character vector. Model IDs to plot.
14861486
#' @param exclude Character vector. Manually exclude variables from plot.
14871487
#' @export
1488-
decomp_plot <- function(InputCollect, OutputCollect, solID = NULL, exclude = NULL) {
1488+
decomp_plot <- function(
1489+
InputCollect, OutputCollect, solID = NULL,
1490+
exclude = NULL, baseline_level = 0) {
1491+
if (is.null(solID) && length(OutputCollect$allSolutions) == 1)
1492+
solID <- OutputCollect$allSolutions
14891493
check_opts(solID, OutputCollect$allSolutions)
1494+
bvars <- baseline_vars(InputCollect, baseline_level)
14901495
intType <- str_to_title(case_when(
14911496
InputCollect$intervalType %in% c("month", "week") ~ paste0(InputCollect$intervalType, "ly"),
14921497
InputCollect$intervalType == "day" ~ "daily",
@@ -1501,7 +1506,14 @@ decomp_plot <- function(InputCollect, OutputCollect, solID = NULL, exclude = NUL
15011506
) %>%
15021507
tidyr::gather("variable", "value", -.data$ds, -.data$solID, -.data$dep_var) %>%
15031508
filter(!.data$variable %in% exclude) %>%
1504-
mutate(variable = factor(.data$variable, levels = rev(unique(.data$variable))))
1509+
mutate(variable = ifelse(
1510+
.data$variable %in% bvars, paste0("Baseline_L", baseline_level), as.character(.data$variable))) %>%
1511+
group_by(.data$solID, .data$ds, .data$variable) %>%
1512+
summarise(value = sum(.data$value, na.rm = TRUE),
1513+
value = sum(.data$value, na.rm = TRUE),
1514+
.groups = "drop") %>%
1515+
arrange(abs(.data$value)) %>%
1516+
mutate(variable = factor(.data$variable, levels = unique(.data$variable)))
15051517
p <- ggplot(df, aes(x = .data$ds, y = .data$value, fill = .data$variable)) +
15061518
facet_grid(.data$solID ~ .) +
15071519
labs(

R/R/response.R

Lines changed: 58 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -23,56 +23,83 @@
2323
#' @examples
2424
#' \dontrun{
2525
#' # Having InputCollect and OutputCollect objects
26+
#' ## Recreate original saturation curve
27+
#' Response <- robyn_response(
28+
#' InputCollect = InputCollect,
29+
#' OutputCollect = OutputCollect,
30+
#' select_model = select_model,
31+
#' metric_name = "facebook_S"
32+
#' )
33+
#' Response$plot
2634
#'
27-
#' # Get marginal response (mResponse) and marginal ROI (mROI) for
28-
#' # the next 1k on 80k for search_S
29-
#' spend1 <- 80000
35+
#' ## Or you can call a JSON file directly (a bit slower)
36+
#' # Response <- robyn_response(
37+
#' # json_file = "your_json_path.json",
38+
#' # dt_input = dt_simulated_weekly,
39+
#' # dt_holidays = dt_prophet_holidays,
40+
#' # metric_name = "facebook_S"
41+
#' # )
42+
#'
43+
#' ## Get the "next 100 dollar" marginal response on Spend1
44+
#' Spend1 <- 20000
3045
#' Response1 <- robyn_response(
3146
#' InputCollect = InputCollect,
3247
#' OutputCollect = OutputCollect,
33-
#' metric_name = "search_S",
34-
#' metric_value = spend1
35-
#' )$response
36-
#' # Get ROI for 80k
37-
#' Response1 / spend1 # ROI for search 80k
48+
#' select_model = select_model,
49+
#' metric_name = "facebook_S",
50+
#' metric_value = Spend1, # total budget for date_range
51+
#' date_range = "last_1" # last two periods
52+
#' )
53+
#' Response1$plot
3854
#'
39-
#' # Get response for 81k
40-
#' spend2 <- spend1 + 1000
55+
#' Spend2 <- Spend1 + 100
4156
#' Response2 <- robyn_response(
4257
#' InputCollect = InputCollect,
4358
#' OutputCollect = OutputCollect,
44-
#' metric_name = "search_S",
45-
#' metric_value = spend2
46-
#' )$response
59+
#' select_model = select_model,
60+
#' metric_name = "facebook_S",
61+
#' metric_value = Spend2,
62+
#' date_range = "last_1"
63+
#' )
64+
#' # ROAS for the 100$ from Spend1 level
65+
#' (Response2$response_total - Response1$response_total) / (Spend2 - Spend1)
4766
#'
48-
#' # Get ROI for 81k
49-
#' Response2 / spend2 # ROI for search 81k
50-
#' # Get marginal response (mResponse) for the next 1k on 80k
51-
#' Response2 - Response1
52-
#' # Get marginal ROI (mROI) for the next 1k on 80k
53-
#' (Response2 - Response1) / (spend2 - spend1)
67+
#' ## Get response from for a given budget and date_range
68+
#' Spend3 <- 100000
69+
#' Response3 <- robyn_response(
70+
#' InputCollect = InputCollect,
71+
#' OutputCollect = OutputCollect,
72+
#' select_model = select_model,
73+
#' metric_name = "facebook_S",
74+
#' metric_value = Spend3, # total budget for date_range
75+
#' date_range = "last_5" # last 5 periods
76+
#' )
77+
#' Response3$plot
5478
#'
55-
#' # Example of getting paid media exposure response curves
56-
#' imps <- 1000000
79+
#' ## Example of getting paid media exposure response curves
80+
#' imps <- 10000000
5781
#' response_imps <- robyn_response(
5882
#' InputCollect = InputCollect,
5983
#' OutputCollect = OutputCollect,
84+
#' select_model = select_model,
6085
#' metric_name = "facebook_I",
6186
#' metric_value = imps
62-
#' )$response
63-
#' response_per_1k_imps <- response_imps / imps * 1000
64-
#' response_per_1k_imps
87+
#' )
88+
#' response_imps$response_total / imps * 1000
89+
#' response_imps$plot
6590
#'
66-
#' # Get response for 80k for search_S from the a certain model SolID
67-
#' # in the current model output in the global environment
68-
#' robyn_response(
91+
#' ## Example of getting organic media exposure response curves
92+
#' sendings <- 30000
93+
#' response_sending <- robyn_response(
6994
#' InputCollect = InputCollect,
7095
#' OutputCollect = OutputCollect,
71-
#' metric_name = "search_S",
72-
#' metric_value = 80000,
73-
#' dt_hyppar = OutputCollect$resultHypParam,
74-
#' dt_coef = OutputCollect$xDecompAgg
96+
#' select_model = select_model,
97+
#' metric_name = "newsletter",
98+
#' metric_value = sendings
7599
#' )
100+
#' # response per 1000 sendings
101+
#' response_sending$response_total / sendings * 1000
102+
#' response_sending$plot
76103
#' }
77104
#' @return List. Response value and plot. Class: \code{robyn_response}.
78105
#' @export

R/man/robyn_outputs.Rd

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

R/man/robyn_response.Rd

Lines changed: 62 additions & 35 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)