google-meridian 1.5.0__tar.gz → 1.5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. {google_meridian-1.5.0/google_meridian.egg-info → google_meridian-1.5.1}/PKG-INFO +2 -2
  2. {google_meridian-1.5.0 → google_meridian-1.5.1}/README.md +1 -1
  3. {google_meridian-1.5.0 → google_meridian-1.5.1/google_meridian.egg-info}/PKG-INFO +2 -2
  4. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/analysis/review/checks.py +118 -116
  5. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/analysis/review/constants.py +3 -3
  6. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/analysis/review/results.py +131 -68
  7. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/analysis/review/reviewer.py +4 -22
  8. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/eda/eda_engine.py +1 -0
  9. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/version.py +1 -1
  10. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/serde/meridian_serde.py +6 -2
  11. {google_meridian-1.5.0 → google_meridian-1.5.1}/LICENSE +0 -0
  12. {google_meridian-1.5.0 → google_meridian-1.5.1}/MANIFEST.in +0 -0
  13. {google_meridian-1.5.0 → google_meridian-1.5.1}/google_meridian.egg-info/SOURCES.txt +0 -0
  14. {google_meridian-1.5.0 → google_meridian-1.5.1}/google_meridian.egg-info/dependency_links.txt +0 -0
  15. {google_meridian-1.5.0 → google_meridian-1.5.1}/google_meridian.egg-info/requires.txt +0 -0
  16. {google_meridian-1.5.0 → google_meridian-1.5.1}/google_meridian.egg-info/top_level.txt +0 -0
  17. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/__init__.py +0 -0
  18. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/analysis/__init__.py +0 -0
  19. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/analysis/analyzer.py +0 -0
  20. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/analysis/optimizer.py +0 -0
  21. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/analysis/review/__init__.py +0 -0
  22. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/analysis/review/configs.py +0 -0
  23. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/analysis/summarizer.py +0 -0
  24. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/analysis/summary_text.py +0 -0
  25. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/analysis/test_utils.py +0 -0
  26. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/analysis/visualizer.py +0 -0
  27. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/backend/__init__.py +0 -0
  28. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/backend/config.py +0 -0
  29. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/backend/test_utils.py +0 -0
  30. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/constants.py +0 -0
  31. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/data/__init__.py +0 -0
  32. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/data/arg_builder.py +0 -0
  33. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/data/data_frame_input_data_builder.py +0 -0
  34. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/data/input_data.py +0 -0
  35. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/data/input_data_builder.py +0 -0
  36. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/data/load.py +0 -0
  37. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/data/nd_array_input_data_builder.py +0 -0
  38. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/data/test_utils.py +0 -0
  39. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/data/time_coordinates.py +0 -0
  40. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/data/validator.py +0 -0
  41. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/mlflow/__init__.py +0 -0
  42. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/mlflow/autolog.py +0 -0
  43. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/__init__.py +0 -0
  44. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/adstock_hill.py +0 -0
  45. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/context.py +0 -0
  46. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/eda/__init__.py +0 -0
  47. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/eda/constants.py +0 -0
  48. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/eda/eda_outcome.py +0 -0
  49. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/eda/eda_spec.py +0 -0
  50. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/equations.py +0 -0
  51. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/knots.py +0 -0
  52. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/media.py +0 -0
  53. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/model.py +0 -0
  54. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/model_test_data.py +0 -0
  55. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/posterior_sampler.py +0 -0
  56. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/prior_distribution.py +0 -0
  57. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/prior_sampler.py +0 -0
  58. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/spec.py +0 -0
  59. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/model/transformers.py +0 -0
  60. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/templates/card.html.jinja +0 -0
  61. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/templates/chart.html.jinja +0 -0
  62. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/templates/chips.html.jinja +0 -0
  63. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/templates/finding.html.jinja +0 -0
  64. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/templates/findings.html.jinja +0 -0
  65. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/templates/formatter.py +0 -0
  66. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/templates/formatter_test.py +0 -0
  67. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/templates/insights.html.jinja +0 -0
  68. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/templates/stats.html.jinja +0 -0
  69. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/templates/style.scss +0 -0
  70. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/templates/summary.html.jinja +0 -0
  71. {google_meridian-1.5.0 → google_meridian-1.5.1}/meridian/templates/table.html.jinja +0 -0
  72. {google_meridian-1.5.0 → google_meridian-1.5.1}/pyproject.toml +0 -0
  73. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/__init__.py +0 -0
  74. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/converters/__init__.py +0 -0
  75. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/converters/dataframe/__init__.py +0 -0
  76. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/converters/dataframe/budget_opt_converters.py +0 -0
  77. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/converters/dataframe/common.py +0 -0
  78. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/converters/dataframe/constants.py +0 -0
  79. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/converters/dataframe/converter.py +0 -0
  80. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/converters/dataframe/dataframe_model_converter.py +0 -0
  81. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/converters/dataframe/marketing_analyses_converters.py +0 -0
  82. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/converters/dataframe/rf_opt_converters.py +0 -0
  83. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/converters/mmm.py +0 -0
  84. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/converters/mmm_converter.py +0 -0
  85. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/converters/sheets.py +0 -0
  86. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/converters/test_data.py +0 -0
  87. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/linkingapi/__init__.py +0 -0
  88. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/linkingapi/constants.py +0 -0
  89. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/linkingapi/url_generator.py +0 -0
  90. {google_meridian-1.5.0 → google_meridian-1.5.1}/scenarioplanner/mmm_ui_proto_generator.py +0 -0
  91. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/__init__.py +0 -0
  92. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/mmm_proto_generator.py +0 -0
  93. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/model_consumer.py +0 -0
  94. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/processors/__init__.py +0 -0
  95. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/processors/budget_optimization_processor.py +0 -0
  96. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/processors/common.py +0 -0
  97. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/processors/marketing_processor.py +0 -0
  98. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/processors/model_fit_processor.py +0 -0
  99. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/processors/model_kernel_processor.py +0 -0
  100. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/processors/model_processor.py +0 -0
  101. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/processors/reach_frequency_optimization_processor.py +0 -0
  102. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/serde/__init__.py +0 -0
  103. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/serde/constants.py +0 -0
  104. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/serde/distribution.py +0 -0
  105. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/serde/eda_spec.py +0 -0
  106. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/serde/function_registry.py +0 -0
  107. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/serde/hyperparameters.py +0 -0
  108. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/serde/inference_data.py +0 -0
  109. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/serde/marketing_data.py +0 -0
  110. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/serde/serde.py +0 -0
  111. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/serde/test_data.py +0 -0
  112. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/test_data.py +0 -0
  113. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/utils/__init__.py +0 -0
  114. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/utils/date_range_bucketing.py +0 -0
  115. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/utils/proto_enum_converter.py +0 -0
  116. {google_meridian-1.5.0 → google_meridian-1.5.1}/schema/utils/time_record.py +0 -0
  117. {google_meridian-1.5.0 → google_meridian-1.5.1}/setup.cfg +0 -0
  118. {google_meridian-1.5.0 → google_meridian-1.5.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: google-meridian
3
- Version: 1.5.0
3
+ Version: 1.5.1
4
4
  Summary: Google's open source mixed marketing model library, helps you understand your return on investment and direct your ad spend with confidence.
5
5
  Author-email: The Meridian Authors <no-reply@google.com>
6
6
  Project-URL: homepage, https://github.com/google/meridian
@@ -210,7 +210,7 @@ To cite this repository:
210
210
  author = {Google Meridian Marketing Mix Modeling Team},
211
211
  title = {Meridian: Marketing Mix Modeling},
212
212
  url = {https://github.com/google/meridian},
213
- version = {1.5.0},
213
+ version = {1.5.1},
214
214
  year = {2025},
215
215
  }
216
216
  ```
@@ -153,7 +153,7 @@ To cite this repository:
153
153
  author = {Google Meridian Marketing Mix Modeling Team},
154
154
  title = {Meridian: Marketing Mix Modeling},
155
155
  url = {https://github.com/google/meridian},
156
- version = {1.5.0},
156
+ version = {1.5.1},
157
157
  year = {2025},
158
158
  }
159
159
  ```
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: google-meridian
3
- Version: 1.5.0
3
+ Version: 1.5.1
4
4
  Summary: Google's open source mixed marketing model library, helps you understand your return on investment and direct your ad spend with confidence.
5
5
  Author-email: The Meridian Authors <no-reply@google.com>
6
6
  Project-URL: homepage, https://github.com/google/meridian
@@ -210,7 +210,7 @@ To cite this repository:
210
210
  author = {Google Meridian Marketing Mix Modeling Team},
211
211
  title = {Meridian: Marketing Mix Modeling},
212
212
  url = {https://github.com/google/meridian},
213
- version = {1.5.0},
213
+ version = {1.5.1},
214
214
  year = {2025},
215
215
  }
216
216
  ```
@@ -15,7 +15,7 @@
15
15
  """Implementation of the Model Quality Checks."""
16
16
 
17
17
  import abc
18
- from collections.abc import Sequence
18
+ from collections.abc import MutableMapping, Sequence
19
19
  import dataclasses
20
20
  from typing import Generic, TypeVar
21
21
  import warnings
@@ -77,31 +77,16 @@ class ConvergenceCheck(
77
77
  if not valid_rhat_items:
78
78
  return results.ConvergenceCheckResult(
79
79
  case=results.ConvergenceCases.CONVERGED,
80
- details={
81
- review_constants.RHAT: np.nan,
82
- review_constants.PARAMETER: np.nan,
83
- review_constants.CONVERGENCE_THRESHOLD: (
84
- self._config.convergence_threshold
85
- ),
86
- },
80
+ config=self._config,
81
+ max_rhat=np.nan,
82
+ max_parameter=np.nan,
87
83
  )
88
84
 
89
85
  max_parameter, max_rhat = max(max_rhats.items(), key=lambda item: item[1])
90
86
 
91
- details = {
92
- review_constants.RHAT: max_rhat,
93
- review_constants.PARAMETER: max_parameter,
94
- review_constants.CONVERGENCE_THRESHOLD: (
95
- self._config.convergence_threshold
96
- ),
97
- }
98
-
99
87
  # Case 1: Converged.
100
88
  if max_rhat < self._config.convergence_threshold:
101
- return results.ConvergenceCheckResult(
102
- case=results.ConvergenceCases.CONVERGED,
103
- details=details,
104
- )
89
+ case = results.ConvergenceCases.CONVERGED
105
90
 
106
91
  # Case 2: Not fully converged, but potentially acceptable.
107
92
  elif (
@@ -109,17 +94,18 @@ class ConvergenceCheck(
109
94
  <= max_rhat
110
95
  < self._config.not_fully_convergence_threshold
111
96
  ):
112
- return results.ConvergenceCheckResult(
113
- case=results.ConvergenceCases.NOT_FULLY_CONVERGED,
114
- details=details,
115
- )
97
+ case = results.ConvergenceCases.NOT_FULLY_CONVERGED
116
98
 
117
99
  # Case 3: Not converged and unacceptable.
118
100
  else: # max_rhat >= divergence_threshold
119
- return results.ConvergenceCheckResult(
120
- case=results.ConvergenceCases.NOT_CONVERGED,
121
- details=details,
122
- )
101
+ case = results.ConvergenceCases.NOT_CONVERGED
102
+
103
+ return results.ConvergenceCheckResult(
104
+ case=case,
105
+ config=self._config,
106
+ max_rhat=max_rhat,
107
+ max_parameter=max_parameter,
108
+ )
123
109
 
124
110
 
125
111
  # ==============================================================================
@@ -131,33 +117,25 @@ class BaselineCheck(
131
117
  """Checks for negative baseline probability."""
132
118
 
133
119
  def run(self) -> results.BaselineCheckResult:
134
- prob = self._analyzer.negative_baseline_probability()
135
- details = {
136
- review_constants.NEGATIVE_BASELINE_PROB: prob,
137
- review_constants.NEGATIVE_BASELINE_PROB_FAIL_THRESHOLD: (
138
- self._config.negative_baseline_prob_fail_threshold
139
- ),
140
- review_constants.NEGATIVE_BASELINE_PROB_REVIEW_THRESHOLD: (
141
- self._config.negative_baseline_prob_review_threshold
142
- ),
143
- }
120
+ prob = float(self._analyzer.negative_baseline_probability())
121
+
144
122
  # Case 1: FAIL
145
123
  if prob > self._config.negative_baseline_prob_fail_threshold:
146
- return results.BaselineCheckResult(
147
- case=results.BaselineCases.FAIL,
148
- details=details,
149
- )
124
+ case = results.BaselineCases.FAIL
125
+
150
126
  # Case 2: REVIEW
151
127
  elif prob >= self._config.negative_baseline_prob_review_threshold:
152
- return results.BaselineCheckResult(
153
- case=results.BaselineCases.REVIEW,
154
- details=details,
155
- )
128
+ case = results.BaselineCases.REVIEW
129
+
156
130
  # Case 3: PASS
157
131
  else:
158
- return results.BaselineCheckResult(
159
- case=results.BaselineCases.PASS, details=details
160
- )
132
+ case = results.BaselineCases.PASS
133
+
134
+ return results.BaselineCheckResult(
135
+ case=case,
136
+ config=self._config,
137
+ negative_baseline_prob=prob,
138
+ )
161
139
 
162
140
 
163
141
  # ==============================================================================
@@ -189,45 +167,40 @@ class BayesianPPPCheck(
189
167
  >= np.abs(total_outcome_actual - total_outcome_expected_mean)
190
168
  )
191
169
 
192
- details = {
193
- review_constants.BAYESIAN_PPP: bayesian_ppp,
194
- }
195
-
196
170
  if bayesian_ppp >= self._config.ppp_threshold:
197
- return results.BayesianPPPCheckResult(
198
- case=results.BayesianPPPCases.PASS,
199
- details=details,
200
- )
171
+ case = results.BayesianPPPCases.PASS
201
172
  else:
202
- return results.BayesianPPPCheckResult(
203
- case=results.BayesianPPPCases.FAIL,
204
- details=details,
205
- )
173
+ case = results.BayesianPPPCases.FAIL
174
+
175
+ return results.BayesianPPPCheckResult(
176
+ case=case,
177
+ config=self._config,
178
+ bayesian_ppp=bayesian_ppp,
179
+ )
206
180
 
207
181
 
208
182
  # ==============================================================================
209
183
  # Check: Goodness of Fit
210
184
  # ==============================================================================
211
- def _set_details_from_gof_dataframe(
212
- details: dict[str, float],
185
+ def _set_metrics_from_gof_dataframe(
186
+ metrics: MutableMapping[str, float],
213
187
  gof_df: pd.DataFrame,
214
188
  geo_granularity: str,
215
- suffix: str | None = None,
189
+ suffix: str,
216
190
  ) -> None:
217
- """Sets the `details` variable of the GoodnessOfFitCheckResult.
191
+ """Sets the `metrics` variable of the GoodnessOfFitCheckResult.
218
192
 
219
193
  This method takes a DataFrame containing goodness of fit metrics and pivots it
220
- to a Series, which is then added to the `details` variable of the
194
+ to a Series, which is then added to the `metrics` variable of the
221
195
  `GoodnessOfFitCheckResult`.
222
196
 
223
197
  Args:
224
- details: A dictionary to store the goodness of fit metrics in.
198
+ metrics: A dictionary to store the goodness of fit metrics in.
225
199
  gof_df: A DataFrame containing predictive accuracy of the whole data (if
226
200
  holdout set is not used) of filtered to a single evaluation set ("all",
227
201
  "train", or "test").
228
202
  geo_granularity: The geo granularity of the data ("geo" or "national").
229
- suffix: A suffix to add to the metric names (e.g., "all", "train", "test").
230
- If None, the metrics are added without a suffix.
203
+ suffix: A suffix to add to the metric names (e.g., "_train", "_test").
231
204
  """
232
205
  gof_metrics_pivoted = gof_df.pivot(
233
206
  index=constants.GEO_GRANULARITY,
@@ -235,22 +208,15 @@ def _set_details_from_gof_dataframe(
235
208
  values=constants.VALUE,
236
209
  )
237
210
  gof_metrics_series = gof_metrics_pivoted.loc[geo_granularity]
238
- if suffix is not None:
239
- details[f"{review_constants.R_SQUARED}_{suffix}"] = gof_metrics_series[
240
- constants.R_SQUARED
241
- ]
242
- details[f"{review_constants.MAPE}_{suffix}"] = gof_metrics_series[
243
- constants.MAPE
244
- ]
245
- details[f"{review_constants.WMAPE}_{suffix}"] = gof_metrics_series[
246
- constants.WMAPE
247
- ]
248
- else:
249
- details[review_constants.R_SQUARED] = gof_metrics_series[
250
- constants.R_SQUARED
251
- ]
252
- details[review_constants.MAPE] = gof_metrics_series[constants.MAPE]
253
- details[review_constants.WMAPE] = gof_metrics_series[constants.WMAPE]
211
+ metrics[f"{review_constants.R_SQUARED}{suffix}"] = gof_metrics_series[
212
+ constants.R_SQUARED
213
+ ]
214
+ metrics[f"{review_constants.MAPE}{suffix}"] = gof_metrics_series[
215
+ constants.MAPE
216
+ ]
217
+ metrics[f"{review_constants.WMAPE}{suffix}"] = gof_metrics_series[
218
+ constants.WMAPE
219
+ ]
254
220
 
255
221
 
256
222
  class GoodnessOfFitCheck(
@@ -269,7 +235,7 @@ class GoodnessOfFitCheck(
269
235
  gof_metrics = gof_df[gof_df[constants.GEO_GRANULARITY] == geo_granularity]
270
236
  is_holdout = constants.EVALUATION_SET_VAR in gof_df.columns
271
237
 
272
- details = {}
238
+ metrics_dict = {}
273
239
  case = results.GoodnessOfFitCases.PASS
274
240
 
275
241
  if is_holdout:
@@ -281,29 +247,71 @@ class GoodnessOfFitCheck(
281
247
  set_metrics = gof_metrics[
282
248
  gof_metrics[constants.EVALUATION_SET_VAR] == evaluation_set
283
249
  ]
284
- _set_details_from_gof_dataframe(
285
- details=details,
250
+ _set_metrics_from_gof_dataframe(
251
+ metrics=metrics_dict,
286
252
  gof_df=set_metrics,
287
253
  geo_granularity=geo_granularity,
288
254
  suffix=suffix,
289
255
  )
290
- if details[f"{review_constants.R_SQUARED}_{suffix}"] <= 0:
256
+ if metrics_dict[f"{review_constants.R_SQUARED}{suffix}"] <= 0:
291
257
  case = results.GoodnessOfFitCases.REVIEW
258
+ return results.GoodnessOfFitCheckResult(
259
+ case=case,
260
+ metrics=results.GoodnessOfFitMetrics(
261
+ r_squared=metrics_dict[
262
+ f"{review_constants.R_SQUARED}{review_constants.ALL_SUFFIX}"
263
+ ],
264
+ mape=metrics_dict[
265
+ f"{review_constants.MAPE}{review_constants.ALL_SUFFIX}"
266
+ ],
267
+ wmape=metrics_dict[
268
+ f"{review_constants.WMAPE}{review_constants.ALL_SUFFIX}"
269
+ ],
270
+ r_squared_train=metrics_dict[
271
+ f"{review_constants.R_SQUARED}{review_constants.TRAIN_SUFFIX}"
272
+ ],
273
+ mape_train=metrics_dict[
274
+ f"{review_constants.MAPE}{review_constants.TRAIN_SUFFIX}"
275
+ ],
276
+ wmape_train=metrics_dict[
277
+ f"{review_constants.WMAPE}{review_constants.TRAIN_SUFFIX}"
278
+ ],
279
+ r_squared_test=metrics_dict[
280
+ f"{review_constants.R_SQUARED}{review_constants.TEST_SUFFIX}"
281
+ ],
282
+ mape_test=metrics_dict[
283
+ f"{review_constants.MAPE}{review_constants.TEST_SUFFIX}"
284
+ ],
285
+ wmape_test=metrics_dict[
286
+ f"{review_constants.WMAPE}{review_constants.TEST_SUFFIX}"
287
+ ],
288
+ ),
289
+ is_holdout=is_holdout,
290
+ )
292
291
  else:
293
- _set_details_from_gof_dataframe(
294
- details=details,
292
+ _set_metrics_from_gof_dataframe(
293
+ metrics=metrics_dict,
295
294
  gof_df=gof_metrics,
296
295
  geo_granularity=geo_granularity,
297
- suffix=None,
296
+ suffix=review_constants.ALL_SUFFIX,
298
297
  )
299
- if details[review_constants.R_SQUARED] <= 0:
298
+ if metrics_dict[review_constants.R_SQUARED] <= 0:
300
299
  case = results.GoodnessOfFitCases.REVIEW
301
-
302
- return results.GoodnessOfFitCheckResult(
303
- case=case,
304
- details=details,
305
- is_holdout=is_holdout,
306
- )
300
+ return results.GoodnessOfFitCheckResult(
301
+ case=case,
302
+ metrics=results.GoodnessOfFitMetrics(
303
+ r_squared=metrics_dict[
304
+ f"{review_constants.R_SQUARED}{review_constants.ALL_SUFFIX}"
305
+ ],
306
+ mape=metrics_dict[
307
+ f"{review_constants.MAPE}{review_constants.ALL_SUFFIX}"
308
+ ],
309
+ wmape=metrics_dict[
310
+ f"{review_constants.WMAPE}{review_constants.ALL_SUFFIX}"
311
+ ],
312
+ ),
313
+ is_holdout=is_holdout,
314
+ )
307
315
 
308
316
 
309
317
  # ==============================================================================
@@ -475,8 +483,10 @@ def _compute_channel_results(
475
483
  channel_results.append(
476
484
  results.ROIConsistencyChannelResult(
477
485
  case=case,
478
- details={},
479
486
  channel_name=channel,
487
+ prior_roi_lo=np.nan,
488
+ prior_roi_hi=np.nan,
489
+ posterior_roi_mean=np.nan,
480
490
  )
481
491
  )
482
492
  for i, channel in enumerate(channel_data.all_channels):
@@ -491,14 +501,10 @@ def _compute_channel_results(
491
501
  channel_results.append(
492
502
  results.ROIConsistencyChannelResult(
493
503
  case=case,
494
- details={
495
- review_constants.PRIOR_ROI_LO: channel_data.prior_roi_los[i],
496
- review_constants.PRIOR_ROI_HI: channel_data.prior_roi_his[i],
497
- review_constants.POSTERIOR_ROI_MEAN: (
498
- channel_data.posterior_means[i]
499
- ),
500
- },
501
504
  channel_name=channel,
505
+ prior_roi_lo=channel_data.prior_roi_los[i],
506
+ prior_roi_hi=channel_data.prior_roi_his[i],
507
+ posterior_roi_mean=channel_data.posterior_means[i],
502
508
  )
503
509
  )
504
510
  return channel_results
@@ -558,7 +564,7 @@ def _compute_aggregate_result(
558
564
 
559
565
  return results.ROIConsistencyCheckResult(
560
566
  case=aggregate_case,
561
- details=aggregate_details,
567
+ aggregate_details=aggregate_details,
562
568
  channel_results=channel_results,
563
569
  )
564
570
 
@@ -734,7 +740,7 @@ class PriorPosteriorShiftCheck(
734
740
  no_shift_channels.append(channel_name)
735
741
  channel_results.append(
736
742
  results.PriorPosteriorShiftChannelResult(
737
- case=case, details={}, channel_name=channel_name
743
+ case=case, channel_name=channel_name
738
744
  )
739
745
  )
740
746
  return channel_results, no_shift_channels
@@ -752,17 +758,13 @@ class PriorPosteriorShiftCheck(
752
758
 
753
759
  if no_shift_channels:
754
760
  agg_case = results.PriorPosteriorShiftAggregateCases.REVIEW
755
- final_details = {
756
- "channels_str": ", ".join(
757
- f"`{channel}`" for channel in no_shift_channels
758
- )
759
- }
760
761
  else:
761
762
  agg_case = results.PriorPosteriorShiftAggregateCases.PASS
762
- final_details = {}
763
763
 
764
764
  return results.PriorPosteriorShiftCheckResult(
765
- case=agg_case, details=final_details, channel_results=channel_results
765
+ case=agg_case,
766
+ channel_results=channel_results,
767
+ no_shift_channels=no_shift_channels,
766
768
  )
767
769
 
768
770
  def run(self) -> results.PriorPosteriorShiftCheckResult:
@@ -32,9 +32,9 @@ NEGATIVE_BASELINE_PROB_REVIEW_THRESHOLD = (
32
32
  R_SQUARED = "r_squared"
33
33
  MAPE = "mape"
34
34
  WMAPE = "wmape"
35
- ALL_SUFFIX = "all"
36
- TRAIN_SUFFIX = "train"
37
- TEST_SUFFIX = "test"
35
+ ALL_SUFFIX = ""
36
+ TRAIN_SUFFIX = "_train"
37
+ TEST_SUFFIX = "_test"
38
38
  EVALUATION_SET_SUFFIXES = (ALL_SUFFIX, TRAIN_SUFFIX, TEST_SUFFIX)
39
39
  MEAN = "mean"
40
40
  VARIANCE = "variance"