add_saturation_observations#
- pymc_marketing.mmm.lift_test.add_saturation_observations(df_lift_test, variable_mapping, saturation_function, model=None, dist=<class 'pymc.distributions.continuous.Gamma'>, name='lift_measurements', get_indices=<function exact_row_indices>, variable_indexer_factory=<function create_variable_indexer>)[source]#
Add saturation observations to the likelihood of the model.
General function to add lift measurements to the likelihood of the model.
Not to be used directly for general use. Use
MMM.add_lift_test_measurements()
oradd_lift_measurements_to_likelihood_from_saturation()
instead.- Parameters:
- df_lift_test
pd.DataFrame
- DataFrame with lift test results with at least the following columns:
x
: x axis value of the lift test.delta_x
: change in x axis value of the lift test.delta_y
: change in y axis value of the lift test.sigma
: standard deviation of the lift test.
Any additional columns are assumed to be coordinates in the model.
- variable_mapping
dict
[str
,str
] Dictionary of variable names to dimensions.
- saturation_function
Callable
[[np.ndarray
],np.ndarray
] Function that takes spend and returns saturation.
- model
Optional
[pm.Model
], optional PyMC model with arbitrary number of coordinates, by default None
- dist
pm.Distribution
class
, optional PyMC distribution to use for the likelihood, by default pm.Gamma
- name
str
, optional Name of the likelihood, by default “lift_measurements”
- get_indices
Callable
[[pd.DataFrame
,pm.Model
],Indices
], optional Function to get the indices of the DataFrame in the model, by default exact_row_indices which assumes that the columns map exactly to the model coordinates.
- variable_indexer_factory
Callable
[[pm.Model
,Indices
],Callable
[[str
],TensorVariable
]], optional Function to create a variable indexer, by default create_variable_indexer which creates a function to index variables in the model. This is used determine the values of the parameters to evaluate the saturation function.
- df_lift_test
Examples
Add lift tests for time-varying saturation to a model:
import pymc as pm import pandas as pd from pymc_marketing.mmm.lift_test import add_saturation_observations df_base_lift_test = pd.DataFrame({ "x": [1, 2, 3], "delta_x": [1, 2, 3], "delta_y": [1, 2, 3], "sigma": [0.1, 0.2, 0.3], }) def saturation_function(x, alpha, lam): return alpha * x / (x + lam) # These are required since alpha and lam # have both channel and date dimensions df_lift_test = df_base_lift_test.assign( channel="channel_1", date=["2019-01-01", "2019-01-02", "2019-01-03"], ) coords = { "channel": ["channel_1", "channel_2"], "date": ["2019-01-01", "2019-01-02", "2019-01-03", "2019-01-04"], } with pm.Model(coords=coords) as model: # Usually defined in a larger model. # Distributions dont matter here, just the shape alpha = pm.HalfNormal("alpha_in_model", dims=("channel", "date")) lam = pm.HalfNormal("lam_in_model", dims="channel") add_saturation_observations( df_lift_test, variable_mapping={ "alpha": "alpha_in_model", "lam": "lam_in_model", }, saturation_function=saturation_function, )
Use the saturation classes to add lift tests to a model. NOTE: This is what happens internally of
MMM
.import pymc as pm import pandas as pd from pymc_marketing.mmm import LogisticSaturation from pymc_marketing.mmm.lift_test import add_saturation_observations saturation = LogisticSaturation() df_base_lift_test = pd.DataFrame({ "x": [1, 2, 3], "delta_x": [1, 2, 3], "delta_y": [1, 2, 3], "sigma": [0.1, 0.2, 0.3], }) df_lift_test = df_base_lift_test.assign( channel="channel_1", ) coords = { "channel": ["channel_1", "channel_2"], } with pm.Model(coords=coords) as model: # Usually defined in a larger model. # Distributions dont matter here, just the shape lam = pm.HalfNormal("saturation_lam", dims="channel") beta = pm.HalfNormal("saturation_beta", dims="channel") add_saturation_observations( df_lift_test, variable_mapping=saturation.variable_mapping, saturation_function=saturation.function, )
Add lift tests for channel, geo saturation functions.
import pymc as pm import pandas as pd from pymc_marketing.mmm import LogisticSaturation from pymc_marketing.mmm.lift_test import add_saturation_observations saturation = LogisticSaturation() df_base_lift_test = pd.DataFrame({ "x": [1, 2, 3], "delta_x": [1, 2, 3], "delta_y": [1, 2, 3], "sigma": [0.1, 0.2, 0.3], }) df_lift_test = df_base_lift_test.assign( channel="channel_1", geo=["G1", "G2", "G2"], ) coords = { "channel": ["channel_1", "channel_2"], "geo": ["G1", "G2", "G3"], } with pm.Model(coords=coords) as model: # Usually defined in a larger model. # Distributions dont matter here, just the shape lam = pm.HalfNormal("saturation_lam", dims=("channel", "geo")) beta = pm.HalfNormal("saturation_beta", dims=("channel", "geo")) add_saturation_observations( df_lift_test, variable_mapping=saturation.variable_mapping, saturation_function=saturation.function, )