@@ -62,6 +62,8 @@ def setUp(self):
6262 key_group = self .key_group ,
6363 key_period = self .key_period ,
6464 key_date = self .key_date )
65+ self .treatment_response = self .data .loc [(self .data [self .key_group ] == 2 ) & (
66+ self .data [self .key_period ] == 1 ), self .key_response ].sum ()
6567
6668 def testFixedCostIROASSummary (self ):
6769 """Checks the TBR results for an holdback experiment."""
@@ -86,16 +88,25 @@ def testFixedCostIROASSummary(self):
8688 r_incr_resp = 147337.122
8789 r_incr_cost = 50000
8890 r_probability = 1.0
91+ r_incr_response_lower = r_lower * r_incr_cost
92+ r_lift = 0.173998
93+ r_lift_lower = 0.165686
8994
9095 # Summary values from python.
9196 iroas = self .iroas_model .summary (
9297 level = level , posterior_threshold = posterior_threshold , tails = tails )
9398 py_estimate = iroas ['estimate' ].iloc [0 ]
9499 py_precision = iroas ['precision' ].iloc [0 ]
95100 py_lower = iroas ['lower' ].iloc [0 ]
101+ py_upper = iroas ['upper' ].iloc [0 ]
96102 py_incr_resp = iroas ['incremental_response' ].iloc [0 ]
97103 py_incr_cost = iroas ['incremental_cost' ].iloc [0 ]
98104 py_probability = iroas ['probability' ].iloc [0 ]
105+ py_incr_resp_lower = iroas ['incremental_response_lower' ].iloc [0 ]
106+ py_incr_resp_upper = iroas ['incremental_response_upper' ].iloc [0 ]
107+ py_lift = iroas ['relative_lift' ].iloc [0 ]
108+ py_lift_lower = iroas ['relative_lift_lower' ].iloc [0 ]
109+ py_lift_upper = iroas ['relative_lift_upper' ].iloc [0 ]
99110
100111 # Must do it like this as the R value is given with lower number of dps.
101112 order_estimate = utils .float_order (r_estimate - py_estimate )
@@ -104,14 +115,23 @@ def testFixedCostIROASSummary(self):
104115 order_iresp = utils .float_order (r_incr_resp - py_incr_resp )
105116 order_icost = utils .float_order (r_incr_cost - py_incr_cost )
106117 order_probability = utils .float_order (r_probability - py_probability )
107-
118+ order_iresp_lower = utils .float_order (r_incr_response_lower -
119+ py_incr_resp_lower )
120+ order_lift = utils .float_order (r_lift - py_lift )
121+ order_lift_lower = utils .float_order (r_lift_lower - py_lift_lower )
108122 # Conduct the tests.
109123 self .assertLess (order_estimate , - 5 )
110124 self .assertLess (order_precision , - 5 )
111125 self .assertLess (order_lower , - 5 )
126+ self .assertEqual (py_upper , np .inf )
112127 self .assertLess (order_iresp , - 2 ) # incremental_response is a larger number.
113128 self .assertLess (order_icost , - 5 )
114129 self .assertLess (order_probability , - 5 )
130+ self .assertLessEqual (order_iresp_lower , - 2 )
131+ self .assertEqual (py_incr_resp_upper , np .inf )
132+ self .assertLessEqual (order_lift , - 4 )
133+ self .assertLessEqual (order_lift_lower , - 4 )
134+ self .assertEqual (py_lift_upper , np .inf )
115135
116136 def testVariableCostIROASSummary (self ):
117137 """Checks the TBR results for an go-dark/heavy-up experiment."""
@@ -134,14 +154,15 @@ def testVariableCostIROASSummary(self):
134154 tails = 1
135155
136156 # Summary values from R, treated as constants.
137- # pylint: disable=invalid-name
138- R_ESTIMATE = 2.946742
139- R_PRECISION = 0.120548
140- R_LOWER = 2.826194
141- R_INCR_RESP = 147337.122
142- R_INCR_COST = 50000
143- R_PROBABILITY = 1.0
144- # pylint: enable=invalid-name
157+ r_estimate = 2.946742
158+ r_precision = 0.120548
159+ r_lower = 2.826194
160+ r_incr_resp = 147337.122
161+ r_incr_cost = 50000
162+ r_probability = 1.0
163+ r_incr_resp_lower = r_lower * r_incr_cost
164+ r_lift = 0.173998
165+ r_lift_lower = 0.165686
145166
146167 # Summary values from python. Specify random_state to make results
147168 # deterministic.
@@ -153,25 +174,40 @@ def testVariableCostIROASSummary(self):
153174 py_estimate = iroas ['estimate' ].iloc [0 ]
154175 py_precision = iroas ['precision' ].iloc [0 ]
155176 py_lower = iroas ['lower' ].iloc [0 ]
177+ py_upper = iroas ['upper' ].iloc [0 ]
156178 py_incr_resp = iroas ['incremental_response' ].iloc [0 ]
157179 py_incr_cost = iroas ['incremental_cost' ].iloc [0 ]
158180 py_probability = iroas ['probability' ].iloc [0 ]
181+ py_incr_resp_lower = iroas ['incremental_response_lower' ].iloc [0 ]
182+ py_incr_resp_upper = iroas ['incremental_response_upper' ].iloc [0 ]
183+ py_lift = iroas ['relative_lift' ].iloc [0 ]
184+ py_lift_lower = iroas ['relative_lift_lower' ].iloc [0 ]
185+ py_lift_upper = iroas ['relative_lift_upper' ].iloc [0 ]
159186
160187 # Must do it like this as the R value is given with lower number of dps.
161- order_estimate = utils .float_order (R_ESTIMATE - py_estimate )
162- order_precision = utils .float_order (R_PRECISION - py_precision )
163- order_lower = utils .float_order (R_LOWER - py_lower )
164- order_iresp = utils .float_order (R_INCR_RESP - py_incr_resp )
165- order_icost = utils .float_order (R_INCR_COST - py_incr_cost )
166- order_probability = utils .float_order (R_PROBABILITY - py_probability )
167-
188+ order_estimate = utils .float_order (r_estimate - py_estimate )
189+ order_precision = utils .float_order (r_precision - py_precision )
190+ order_lower = utils .float_order (r_lower - py_lower )
191+ self .assertEqual (py_upper , np .inf )
192+ order_iresp = utils .float_order (r_incr_resp - py_incr_resp )
193+ order_icost = utils .float_order (r_incr_cost - py_incr_cost )
194+ order_probability = utils .float_order (r_probability - py_probability )
195+ order_iresp_lower = utils .float_order (r_incr_resp_lower -
196+ py_incr_resp_lower )
197+ order_lift = utils .float_order (r_lift - py_lift )
198+ order_lift_lower = utils .float_order (r_lift_lower - py_lift_lower )
168199 # Conduct the tests. Easier threshold as we added some noise.
169200 self .assertLess (order_estimate , - 2 )
170201 self .assertLess (order_precision , - 2 )
171202 self .assertLess (order_lower , - 2 )
172203 self .assertLess (order_iresp , - 2 ) # incremental_response is a larger number.
173204 self .assertLess (order_icost , - 2 )
174205 self .assertLess (order_probability , - 2 )
206+ self .assertLessEqual (order_iresp_lower , - 2 )
207+ self .assertEqual (py_incr_resp_upper , np .inf )
208+ self .assertLessEqual (order_lift , - 4 )
209+ self .assertLessEqual (order_lift_lower , - 4 )
210+ self .assertEqual (py_lift_upper , np .inf )
175211
176212 def testVariableCostIROASSummaryTwoTails (self ):
177213 """Checks the TBR results when reporting two sided CI."""
@@ -194,15 +230,18 @@ def testVariableCostIROASSummaryTwoTails(self):
194230 tails = 2
195231
196232 # Summary values from R, treated as constants.
197- # pylint: disable=invalid-name
198- R_ESTIMATE = 2.947012
199- R_PRECISION = 0.1557932
200- R_LOWER = 2.79135
201- R_UPPER = 3.102936
202- R_INCR_RESP = 147337.122
203- R_INCR_COST = 50000
204- R_PROBABILITY = 1.0
205- # pylint: enable=invalid-name
233+ r_estimate = 2.947012
234+ r_precision = 0.1557932
235+ r_lower = 2.79135
236+ r_upper = 3.102936
237+ r_incr_resp = 147337.122
238+ r_incr_cost = 50000
239+ r_probability = 1.0
240+ r_incr_resp_lower = r_lower * r_incr_cost
241+ r_incr_resp_upper = r_upper * r_incr_cost
242+ r_lift = 0.173998
243+ r_lift_lower = 0.163273
244+ r_lift_upper = 0.184885
206245
207246 # Summary values from python. Specify random_state to make results
208247 # deterministic.
@@ -218,15 +257,31 @@ def testVariableCostIROASSummaryTwoTails(self):
218257 py_incr_resp = iroas ['incremental_response' ].iloc [0 ]
219258 py_incr_cost = iroas ['incremental_cost' ].iloc [0 ]
220259 py_probability = iroas ['probability' ].iloc [0 ]
221-
260+ py_incr_resp_lower = iroas ['incremental_response_lower' ].iloc [0 ]
261+ py_incr_resp_upper = iroas ['incremental_response_upper' ].iloc [0 ]
262+ py_lift = iroas ['relative_lift' ].iloc [0 ]
263+ py_lift_lower = iroas ['relative_lift_lower' ].iloc [0 ]
264+ py_lift_upper = iroas ['relative_lift_upper' ].iloc [0 ]
265+
266+ print (r_lift_lower )
267+ print (py_lift_lower )
222268 # Must do it like this as the R value is given with lower number of dps.
223- order_estimate = utils .float_order (R_ESTIMATE - py_estimate )
224- order_precision = utils .float_order (R_PRECISION - py_precision )
225- order_lower = utils .float_order (R_LOWER - py_lower )
226- order_upper = utils .float_order (R_UPPER - py_upper )
227- order_iresp = utils .float_order (R_INCR_RESP - py_incr_resp )
228- order_icost = utils .float_order (R_INCR_COST - py_incr_cost )
229- order_probability = utils .float_order (R_PROBABILITY - py_probability )
269+ order_estimate = utils .float_order (r_estimate - py_estimate )
270+ order_precision = utils .float_order (r_precision - py_precision )
271+ order_lower = utils .float_order (r_lower - py_lower )
272+ order_upper = utils .float_order (r_upper - py_upper )
273+ order_iresp = utils .float_order (r_incr_resp - py_incr_resp )
274+ order_icost = utils .float_order (r_incr_cost - py_incr_cost )
275+ order_probability = utils .float_order (r_probability - py_probability )
276+ # Use relative error for incremental response due to different RNG in R and
277+ # Python
278+ order_iresp_lower = utils .float_order (
279+ (r_incr_resp_lower - py_incr_resp_lower ) * 100 / r_incr_resp_lower )
280+ order_iresp_upper = utils .float_order (
281+ (r_incr_resp_upper - py_incr_resp_upper ) * 100 / r_incr_resp_upper )
282+ order_lift = utils .float_order (r_lift - py_lift )
283+ order_lift_lower = utils .float_order (r_lift_lower - py_lift_lower )
284+ order_lift_upper = utils .float_order (r_lift_upper - py_lift_upper )
230285
231286 # Conduct the tests. Easier threshold as we added some noise.
232287 self .assertLess (order_estimate , - 2 )
@@ -236,6 +291,11 @@ def testVariableCostIROASSummaryTwoTails(self):
236291 self .assertLess (order_iresp , - 2 ) # incremental_response is a larger number.
237292 self .assertLess (order_icost , - 2 )
238293 self .assertLess (order_probability , - 2 )
294+ self .assertLessEqual (order_iresp_lower , - 2 )
295+ self .assertLessEqual (order_iresp_upper , - 2 )
296+ self .assertLessEqual (order_lift , - 4 )
297+ self .assertLessEqual (order_lift_lower , - 4 )
298+ self .assertLessEqual (order_lift_upper , - 4 )
239299
240300 def testIROASSummaryWithCooldown (self ):
241301 """Checks the TBR results when including the cooldown period in the analysis."""
0 commit comments