website/docs/GettingStarted/MultiCellWalkthrough.md

sidebar_position: 3

Multi-Cell Walkthrough

Introduction to Multi-Cell GeoLifts

One of the key competitive advantages of Geo-Experimental techniques such as GeoLift is that they can empower decision-makers to make apples-to-apples comparisons across different channels. Multi-Cell experiments on GeoLift take this concept to the next level by allowing users to easily set-up and analyze complex experimental designs where more than one channel or strategy is measured simultaneously. With Multi-Cell GeoLifts you can:

Multi-Cell Tests with GeoLift

Starting on v2.5 of GeoLift, a new set of functions were introduced to run Multi-Cell tests. In this context, each cell refers to a different test group which will be used to measure and compare across strategies or channels. After identifying the KPI that will be measured with the experiment, the typical flow of a Multi-Cell experiment is as follows:

  1. Determine how many cells or test groups will be used in the experiment.

  2. Run MultiCellMarketSelection with the pre-determined number of cells (k). This function will return k optimal simultaneous test groups.

  3. Use MultiCellPower to obtain a detailed Power Curve and required investment for each cell.

  4. [Optional]: MultiCellWinner can provide valuable information if the test's objective is to determine whether a strategy/channel is statistically significantly better than the others. The output of this function will specify what would be needed for a cell to be declared winner based on statistical tests of equivalence.

  5. Run the campaigns.

  6. Run inference with GeoLiftMultiCell, find out the true incremental value of each cell, conclude whether there was a winner, and use the results to optimize your strategy!

After downloading GeoLift v2.5 (or greater), the first step is to load the package:

# Load libraries
library(GeoLift)
library(dplyr)

1. Determining the number of Cells

Figuring out how many cells will be measured in a GeoLift test is a crucial first step in the Multi-Cell process. Here, it is important to take into consideration that each cell will be measured by one or more test regions (city, state, DMA, etc.). Therefore, the total number of cells that can be measured with a GeoLift is bounded by the available data. Our recommendation is to be very conservative with the number of cells in a single GeoLift study.

For this Walkthrough we will explore a cross-channel test to measure and compare the Lift of our largest Social Media and Paid Search channels. We will use the sample data included in this package:

data(GeoLift_PreTest)

# Read into GeoLifts format with GeoDataRead
GeoTestData_PreTest <- GeoDataRead(data = GeoLift_PreTest,
                                    date_id = "date",
                                    location_id = "location",
                                    Y_id = "Y",
                                    X = c(), #empty list as we have no covariates
                                    format = "yyyy-mm-dd",
                                    summary = TRUE)

# Plot the KPI's historical values
GeoPlot(GeoTestData_PreTest)

GeoPlot

The dataset contains the pre-treatment daily sales for 40 US cities across 90 days. The data-frame contains three variables: location (city), date (in “yyyy-mm-dd” format), and Y (number of conversions/KPI in each day/location).

Finally, it is important to highlight the trade-off between number of cells in a Multi-Cell GeoLift test and the model fit. Given that increasing the number of cells necessarily decreases the total available units in the pool of controls, adding too many cells can significantly reduce the model fit and accuracy. In our example, given that we only have 40 cities in total, it would be advisable to not run a Multi-Cell test with more than 2 or 3 cells.

2. Finding test markets with MultiCellMarketSelection

Once the number of cells, k, is determined, we can proceed to find the optimal test markets for each cell through MultiCellMarketSelection(). Relying on a sampling method defined by the user, the algorithm will create k similar groups. For each group, the algorithm will run a series of simulations to determine the best combinations of test and control locations.

The key parameters needed to run this function are:

Taking this inputs into consideration, we find:

set.seed(8) #To replicate the results
Markets <- MultiCellMarketSelection(data = GeoTestData_PreTest,
                                 k = 2,
                                 sampling_method = "systematic",
                                 top_choices = 10,
                                 N = c(2,3),
                                 effect_size = seq(0, 0.25, 0.025),
                                 treatment_periods = c(15),
                                 lookback_window = 1,
                                 cpic = c(7, 7.50),
                                 alpha = 0.1,
                                 model = "None",
                                 fixed_effects = TRUE,
                                 Correlations = TRUE,
                                 side_of_test = "one_sided")
Markets

##    cell ID                            location duration EffectSize
## 1     1  1                 chicago, cincinnati       15      0.025
## 2     2  1                     baltimore, reno       15      0.025
## 3     1  2            cleveland, oklahoma city       15      0.050
## 4     2  2                       houston, reno       15      0.025
## 5     1  3               las vegas, saint paul       15      0.025
## 6     2  3              honolulu, indianapolis       15      0.025
## 7     1  4                nashville, san diego       15      0.025
## 8     2  4             houston, portland, reno       15      0.025
## 9     1  5               philadelphia, phoenix       15      0.025
## 10    2  5         denver, memphis, washington       15      0.050
## 11    1  6    cleveland, dallas, oklahoma city       15      0.025
## 12    2  6               baton rouge, portland       15      0.025
## 13    1  7               detroit, jacksonville       15      0.025
## 14    2  7                     denver, memphis       15      0.050
## 15    1  8         atlanta, chicago, nashville       15      0.050
## 16    2  8                 memphis, washington       15      0.025
## 17    1  9                  atlanta, nashville       15      0.050
## 18    2  9      baton rouge, houston, portland       15      0.025
## 19    1 10 columbus, jacksonville, minneapolis       15      0.025
## 20    2 10                     miami, portland       15      0.075
##    AvgScaledL2Imbalance abs_lift_in_zero Investment ProportionTotal_Y   Holdout
## 1             0.2587293            0.001   15548.58        0.03418832 0.9658117
## 2             0.3202672            0.002   20166.19        0.04151842 0.9584816
## 3             0.5582169            0.001   60865.35        0.06599073 0.9340093
## 4             0.4149685            0.003   20507.62        0.04282716 0.9571728
## 5             0.7667228            0.003   20827.62        0.04571975 0.9542802
## 6             0.3044968            0.004   16648.88        0.03307948 0.9669205
## 7             0.4379696            0.005   17827.78        0.03891756 0.9610824
## 8             0.2643562            0.005   28790.25        0.05949740 0.9405026
## 9             0.5666373            0.007   45695.48        0.09829630 0.9017037
## 10            0.6200586            0.008   57326.25        0.05922727 0.9407727
## 11            0.6198624            0.008   36378.83        0.07923764 0.9207624
## 12            0.2284603            0.010   16299.00        0.03289916 0.9671008
## 13            0.3317333            0.008   13281.10        0.02940561 0.9705944
## 14            0.6591485            0.009   42621.00        0.04433701 0.9556630
## 15            0.5302774            0.008   55532.05        0.06089060 0.9391094
## 16            0.4803747            0.011   19126.69        0.03939854 0.9606015
## 17            0.6205455            0.008   40863.20        0.04449547 0.9555045
## 18            0.2413871            0.015   28416.38        0.05780466 0.9421953
## 19            0.3246004            0.010   24523.98        0.05485904 0.9451410
## 20            0.3733400            0.010   50877.56        0.03495877 0.9650412
##    rank
## 1     1
## 2     1
## 3     2
## 4     2
## 5     2
## 6     3
## 7     4
## 8     4
## 9     5
## 10    5
## 11    6
## 12    6
## 13    6
## 14    6
## 15    8
## 16    8
## 17    8
## 18    9
## 19    8
## 20    9

The resulting table contains optimal test designs for this two-cell test as well as some model-fit metrics for each selection. The columns in the results represent:

Exploring the results of MultiCellMarketSelection we find that locations "chicago, cincinnati" for Cell 1 and "honolulu, indianapolis" in Cell 2 provide excelent values across all model-fit metrics such as a low EffectSize, small AvgScaledL2Imbalance, an abs_lift_in_zero close to zero, and a very similar value of ProportionTotal_Y.

We could define our Multi-Cell test markets as a list:

# Cell and Market IDs in a list
test_locs <- list(cell_1 = 1, #chicago, cincinnati
                  cell_2 = 3) #honolulu, indianapolis

Moreover, we could plot these results to observe how the model fits the historical data.


plot(Markets,
     test_markets = test_locs,
     type = "Lift",
     stacked = TRUE)

MarketSelection

3. Detailed Power Curves

Perhaps the most important piece of part of any Market Selection process is to obtain and analyze the test's Power Curve. These curves tell us how sensible our test is at detecting a given Lift, it's statistical power, and give us a good estimate of the necessary budget needed to run the Multi-Cell test. The MultiCellPower function can be used to calculate the Power Curves for a given set of cells through simulations on the historical data.

The MultiCellPower function is very easy to use as it will leverage the set-up and results we obtained from MultiCellMarketSelection. The most important parameters to calculate the Power Curves are:

Power <- MultiCellPower(Markets,
                        test_markets = test_locs,
                        effect_size =  seq(-0.5, 0.5, 0.05),
                        lookback_window = 7)

Plotting the results shows the Power Curve for each cell.

plot(Power,
     actual_values = TRUE,
     smoothed_values = FALSE,
     show_mde = TRUE,
     breaks_x_axis = 15,
     stacked = TRUE)

PowerCurves

The plot shows that both Power Curves are ideal as they are: symmetric, centered at zero, and have relatively small effect sizes needed to accurately detect lift (\~5%). Moreover, we observe that, despite different cpics, an investment of $50,000 per cell should be more than enough to achieve a significant Lift.

[Optional]: MultiCellWinner

While most of the times the objective of a Multi-Cell test is simply to accurately measure the incremental effect of different channels/strategies, sometimes we want to go a step further and declare which one of the competing cells is statistically significantly better or worse than the others. In this case, we can use the MultiCellWinner function, to determine what must happen for a cell to be declared a "Winner". This function works by answering the following question: for a given baseline Effect Size, how much better must the incremental Return on Ad Spend (iROAS) of a cell be so that it provides a statistically significantly better Lift overall?

The most important parameters of the MultiCellWinner function are:

Winners <- MultiCellWinner(Power,
                           effect_size = 0.1,
                           geolift_type = "standard",
                           ROAS = seq(1,10,0.5),
                           alpha = 0.1,
                           method = "conformal",
                           stat_test = "Positive"
)
Winners
##                cell_A incremental_A lowerCI_Cell_A upperCI_Cell_A
## 1 chicago, cincinnati      78534.65        76612.9         557051
##                   cell_B incremental_B lowerCI_Cell_B upperCI_Cell_B duration
## 1 honolulu, indianapolis      9065.861        3467.71        75443.9       15
##   ROAS
## 1    9

These results show that Cell 1 would need to be 9x more effective than Cell 2 to be declared a "Winner".

4. Campaign Execution

After successfully selecting the test markets with MultiCellMarketSelection and GeoLiftPower, the campaigns can be executed. For this test we will run ads on Social Media for the cities of Chicago and Cincinnati (Cell 1), Paid Search ads for the cities of Honolulu and Indianapolis (Cell 2), and holdout the rest of the locations in our data-set for a 15-day test.

We can use the simulated Multi-Cell data included in the GeoLift package as follows:

data(GeoLift_Test_MultiCell)

# Read test data
GeoTestData_Test <- GeoDataRead(data = GeoLift_Test_MultiCell,
                                    date_id = "date",
                                    location_id = "location",
                                    Y_id = "Y",
                                    X = c(), #empty list as we have no covariates
                                    format = "yyyy-mm-dd",
                                    summary = TRUE)

## ##################################
## #####       Summary       #####
## ##################################
##
## * Raw Number of Locations: 40
## * Time Periods: 105
## * Final Number of Locations (Complete): 40
# Plot the historical and test data
GeoPlot(GeoTestData_Test,
        treatment_start = 91)

TreatmentGeoPlot

5. Multi-Cell Inference for GeoLift

The final step in the process is to calculate the Lift generated by our Social Media and Paid Search campaigns. We can leverage the GeoLiftMultiCell function to easily perform statistical inference on our test. The key parameters of this function are:

# First we specify our test locations as a list
test_locations <- list(cell_1 = list("chicago", "cincinnati"),
                       cell_2 = list("honolulu", "indianapolis"))

#Then, we run MultiCellResults
MultiCellResults <- GeoLiftMultiCell(data = GeoTestData_Test,
                                     locations = test_locations,
                                     treatment_start_time = 91,
                                     treatment_end_time = 105,
                                     alpha = 0.1,
                                     model = "best",
                                     fixed_effects = TRUE,
                                     ConfidenceIntervals = TRUE,
                                     method = "conformal",
                                     stat_test = "Positive",
                                     winner_declaration = TRUE)

## Selected Ridge as best model.
## Selected Ridge as best model.
##
## ##################################
## ##### Pairwise  Comparisons #####
## ##################################
##                Cell_A  Lower_A   Upper_A                 Cell_B Lower_B
## 1 chicago, cincinnati 16673.88 146162.26 honolulu, indianapolis 8745.23
##     Upper_B Winner
## 1 118669.62   <NA>
MultiCellResults

## ##################################
## #####     Cell 1 Results    #####
## ##################################
## Test results for 15 treatment periods, from time-stamp 91 to 105 for test markets:
## 1 CHICAGO
## 2 CINCINNATI
## ##################################
## #####     Test Statistics    #####
## ##################################
##
## Percent Lift: 22.8%
##
## p-value: 0
##
## Incremental Y: 20215
##
## Average Estimated Treatment Effect (ATT): 673.819
##
## The results are significant at a 95% level. (ONE-SIDED POSITIVE LIFT TEST)
##
## There is a 0% chance of observing an effect this large or larger assuming treatment effect is zero.
## ##################################
## #####     Cell 2 Results    #####
## ##################################
## Test results for 15 treatment periods, from time-stamp 91 to 105 for test markets:
## 1 HONOLULU
## 2 INDIANAPOLIS
## ##################################
## #####     Test Statistics    #####
## ##################################
##
## Percent Lift: 7.1%
##
## p-value: 0
##
## Incremental Y: 6493
##
## Average Estimated Treatment Effect (ATT): 216.423
##
## The results are significant at a 95% level. (ONE-SIDED POSITIVE LIFT TEST)
##
## There is a 0% chance of observing an effect this large or larger assuming treatment effect is zero.

The results show that the Social Media campaign had a significant Lift equal to 22.8% while the Paid Search campaigns generated a 7.1% Lift. And while the results of the test show a higher Lift by Cell 1, the wide Confidence Intervals do not allow us to declare a winner at a 90% confidence level. We can dig deeper into the results through the summary() of our Multi-Cell GeoLift object. The summary() method has two options based on the table parameter:

  1. If table = TRUE a summary table of the results per cell will be printed.
#Short summary of the results
summary(MultiCellResults, table = TRUE)

## | Cell|Location               | Duration|Lift  | Incremental|     ATT| pValue|Stat_Test                    | Stat_Sig|Prognostic_Func |Winner |
## |----:|:----------------------|--------:|:-----|-----------:|-------:|------:|:----------------------------|--------:|:---------------|:------|
## |    1|CHICAGO, CINCINNATI    |       15|22.8% |       20215| 673.819|      0|ONE-SIDED POSITIVE LIFT TEST |        1|RIDGE           |       |
## |    2|HONOLULU, INDIANAPOLIS |       15|7.1%  |        6493| 216.423|      0|ONE-SIDED POSITIVE LIFT TEST |        1|RIDGE           |       |
  1. If table = FALSE the complete summary method for each cell will be outputted.
# Deep dive into the results
summary(MultiCellResults, table = FALSE)

## ##################################
## #####     Cell 1 Results    #####
## ##################################
##
## GeoLift Results Summary
## ##################################
## #####     Test Statistics    #####
## ##################################
##
## * Average ATT: 673.819
## * Percent Lift: 22.8%
## * Incremental Y: 20215
## * P-value: 0
## * 90% Confidence Interval: (16673.879, 146162.255)
##
## ##################################
## #####   Balance Statistics   #####
## ##################################
##
## * L2 Imbalance: 956.678
## * Scaled L2 Imbalance: 0.1694
## * Percent improvement from naive model: 83.06%
## * Average Estimated Bias: -0.441
##
## ##################################
## #####     Model Weights      #####
## ##################################
##
## * Prognostic Function: RIDGE
##
## * Model Weights:
##  * portland: 0.2121
##  * austin: 0.1521
##  * nashville: 0.1463
##  * san diego: 0.1371
##  * minneapolis: 0.1364
##  * new york: 0.06
##  * baton rouge: 0.0558
##  * reno: 0.0474
##  * miami: 0.0359
##  * atlanta: 0.0118
##  * houston: 0.0044
##  * san antonio: 0.0041
##  * salt lake city: -0.0013
##  * oakland: -8e-04
##  * philadelphia: -7e-04
##  * oklahoma city: -4e-04
##  * baltimore: 2e-04
##  * las vegas: 2e-04
##  * dallas: 2e-04
##  * new orleans: -1e-04
##  * san francisco: -1e-04
##  * boston: -1e-04
##  * columbus: 1e-04
##  * washington: -1e-04
##  * kansas city: -1e-04
##  * phoenix: -1e-04
##  * memphis: -1e-04
##  * milwaukee: -1e-04
##  * cleveland: -1e-04
##  * saint paul: 1e-04
##
## ##################################
## #####     Cell 2 Results    #####
## ##################################
##
## GeoLift Results Summary
## ##################################
## #####     Test Statistics    #####
## ##################################
##
## * Average ATT: 216.423
## * Percent Lift: 7.1%
## * Incremental Y: 6493
## * P-value: 0
## * 90% Confidence Interval: (8745.226, 118669.618)
##
## ##################################
## #####   Balance Statistics   #####
## ##################################
##
## * L2 Imbalance: 1508.472
## * Scaled L2 Imbalance: 0.326
## * Percent improvement from naive model: 67.4%
## * Average Estimated Bias: 11.782
##
## ##################################
## #####     Model Weights      #####
## ##################################
##
## * Prognostic Function: RIDGE
##
## * Model Weights:
##  * austin: 0.3567
##  * tucson: 0.2351
##  * portland: 0.1744
##  * nashville: 0.0988
##  * baton rouge: 0.0823
##  * detroit: 0.0445
##  * orlando: 0.0391
##  * phoenix: -0.0136
##  * columbus: -0.0129
##  * salt lake city: -0.0125
##  * memphis: -0.0106
##  * oklahoma city: 0.0102
##  * miami: -0.0093
##  * houston: 0.0073
##  * las vegas: -0.007
##  * baltimore: -0.0066
##  * san francisco: -0.006
##  * jacksonville: 0.006
##  * kansas city: 0.0054
##  * milwaukee: 0.0043
##  * cleveland: 0.0042
##  * philadelphia: 0.0041
##  * denver: -0.0032
##  * new orleans: -0.0028
##  * los angeles: 0.0023
##  * washington: 0.0023
##  * minneapolis: 0.002
##  * san diego: 0.0017
##  * dallas: 0.0016
##  * san antonio: 0.0014
##  * reno: 0.0014
##  * atlanta: -0.0013
##  * boston: 0.0013
##  * new york: -9e-04
##  * oakland: 6e-04
##  * saint paul: -1e-04
##

Finally, we can plot the results to observe both the Lift and ATT plots.

plot(MultiCellResults, type = "Lift", stacked = TRUE)

ResultsLift

plot(MultiCellResults, type = "ATT", stacked = TRUE)

ResultsATT



facebookincubator/GeoLift documentation built on May 31, 2024, 10:09 a.m.