google-meridian 1.3.1__py3-none-any.whl → 1.4.0__py3-none-any.whl
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.
- {google_meridian-1.3.1.dist-info → google_meridian-1.4.0.dist-info}/METADATA +13 -9
- google_meridian-1.4.0.dist-info/RECORD +108 -0
- {google_meridian-1.3.1.dist-info → google_meridian-1.4.0.dist-info}/top_level.txt +1 -0
- meridian/analysis/__init__.py +1 -2
- meridian/analysis/analyzer.py +0 -1
- meridian/analysis/optimizer.py +5 -3
- meridian/analysis/review/checks.py +81 -30
- meridian/analysis/review/constants.py +4 -0
- meridian/analysis/review/results.py +40 -9
- meridian/analysis/summarizer.py +8 -3
- meridian/analysis/test_utils.py +934 -485
- meridian/analysis/visualizer.py +11 -7
- meridian/backend/__init__.py +53 -5
- meridian/backend/test_utils.py +72 -0
- meridian/constants.py +2 -0
- meridian/data/load.py +2 -0
- meridian/data/test_utils.py +82 -10
- meridian/model/__init__.py +2 -0
- meridian/model/context.py +925 -0
- meridian/model/eda/__init__.py +0 -1
- meridian/model/eda/constants.py +13 -2
- meridian/model/eda/eda_engine.py +299 -37
- meridian/model/eda/eda_outcome.py +21 -1
- meridian/model/equations.py +418 -0
- meridian/model/knots.py +75 -47
- meridian/model/model.py +93 -792
- meridian/{analysis/templates → templates}/card.html.jinja +1 -1
- meridian/{analysis/templates → templates}/chart.html.jinja +1 -1
- meridian/{analysis/templates → templates}/chips.html.jinja +1 -1
- meridian/{analysis → templates}/formatter.py +12 -1
- meridian/templates/formatter_test.py +216 -0
- meridian/{analysis/templates → templates}/insights.html.jinja +1 -1
- meridian/{analysis/templates → templates}/stats.html.jinja +1 -1
- meridian/{analysis/templates → templates}/style.css +1 -1
- meridian/{analysis/templates → templates}/style.scss +1 -1
- meridian/{analysis/templates → templates}/summary.html.jinja +4 -2
- meridian/{analysis/templates → templates}/table.html.jinja +1 -1
- meridian/version.py +1 -1
- scenarioplanner/__init__.py +42 -0
- scenarioplanner/converters/__init__.py +25 -0
- scenarioplanner/converters/dataframe/__init__.py +28 -0
- scenarioplanner/converters/dataframe/budget_opt_converters.py +383 -0
- scenarioplanner/converters/dataframe/common.py +71 -0
- scenarioplanner/converters/dataframe/constants.py +137 -0
- scenarioplanner/converters/dataframe/converter.py +42 -0
- scenarioplanner/converters/dataframe/dataframe_model_converter.py +70 -0
- scenarioplanner/converters/dataframe/marketing_analyses_converters.py +543 -0
- scenarioplanner/converters/dataframe/rf_opt_converters.py +314 -0
- scenarioplanner/converters/mmm.py +743 -0
- scenarioplanner/converters/mmm_converter.py +58 -0
- scenarioplanner/converters/sheets.py +156 -0
- scenarioplanner/converters/test_data.py +714 -0
- scenarioplanner/linkingapi/__init__.py +47 -0
- scenarioplanner/linkingapi/constants.py +27 -0
- scenarioplanner/linkingapi/url_generator.py +131 -0
- scenarioplanner/mmm_ui_proto_generator.py +354 -0
- schema/__init__.py +15 -0
- schema/mmm_proto_generator.py +71 -0
- schema/model_consumer.py +133 -0
- schema/processors/__init__.py +77 -0
- schema/processors/budget_optimization_processor.py +832 -0
- schema/processors/common.py +64 -0
- schema/processors/marketing_processor.py +1136 -0
- schema/processors/model_fit_processor.py +367 -0
- schema/processors/model_kernel_processor.py +117 -0
- schema/processors/model_processor.py +412 -0
- schema/processors/reach_frequency_optimization_processor.py +584 -0
- schema/test_data.py +380 -0
- schema/utils/__init__.py +1 -0
- schema/utils/date_range_bucketing.py +117 -0
- google_meridian-1.3.1.dist-info/RECORD +0 -76
- meridian/model/eda/meridian_eda.py +0 -220
- {google_meridian-1.3.1.dist-info → google_meridian-1.4.0.dist-info}/WHEEL +0 -0
- {google_meridian-1.3.1.dist-info → google_meridian-1.4.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -88,7 +88,7 @@ AXIS_CONFIG = immutabledict.immutabledict({
|
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
_template_loader = jinja2.FileSystemLoader(
|
|
91
|
-
os.path.abspath(os.path.dirname(__file__))
|
|
91
|
+
os.path.abspath(os.path.dirname(__file__))
|
|
92
92
|
)
|
|
93
93
|
|
|
94
94
|
|
|
@@ -206,6 +206,17 @@ def create_template_env() -> jinja2.Environment:
|
|
|
206
206
|
)
|
|
207
207
|
|
|
208
208
|
|
|
209
|
+
def create_summary_html(
|
|
210
|
+
template_env: jinja2.Environment,
|
|
211
|
+
title: str,
|
|
212
|
+
cards: Sequence[str],
|
|
213
|
+
) -> str:
|
|
214
|
+
"""Creates the HTML snippet for the summary page."""
|
|
215
|
+
return template_env.get_template('summary.html.jinja').render(
|
|
216
|
+
title=title, cards=cards
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
|
|
209
220
|
def create_card_html(
|
|
210
221
|
template_env: jinja2.Environment,
|
|
211
222
|
card_spec: CardSpec,
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# Copyright 2025 The Meridian Authors.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from xml.etree import ElementTree as ET
|
|
16
|
+
|
|
17
|
+
from absl.testing import absltest
|
|
18
|
+
from absl.testing import parameterized
|
|
19
|
+
from meridian.templates import formatter
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class FormatterTest(parameterized.TestCase):
|
|
23
|
+
|
|
24
|
+
def test_custom_title_params_correct(self):
|
|
25
|
+
title_params = formatter.custom_title_params('test title')
|
|
26
|
+
self.assertEqual(
|
|
27
|
+
title_params.to_dict(),
|
|
28
|
+
{
|
|
29
|
+
'anchor': 'start',
|
|
30
|
+
'color': '#3C4043',
|
|
31
|
+
'font': 'Google Sans Display',
|
|
32
|
+
'fontSize': 18,
|
|
33
|
+
'fontWeight': 'normal',
|
|
34
|
+
'offset': 10,
|
|
35
|
+
'text': 'test title',
|
|
36
|
+
},
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
def test_bar_chart_width(self):
|
|
40
|
+
num_bars = 3
|
|
41
|
+
width = formatter.bar_chart_width(num_bars)
|
|
42
|
+
self.assertEqual(width, 186)
|
|
43
|
+
|
|
44
|
+
@parameterized.named_parameters(
|
|
45
|
+
('zero_percent', 0.0, '0%'),
|
|
46
|
+
('less_than_one_percent', 0.0005, '0.05%'),
|
|
47
|
+
('one_percent', 0.01, '1%'),
|
|
48
|
+
('greater_than_one_percent', 0.4257, '43%'),
|
|
49
|
+
)
|
|
50
|
+
def test_format_percent_correct(self, percent, expected):
|
|
51
|
+
formatted_percent = formatter.format_percent(percent)
|
|
52
|
+
self.assertEqual(formatted_percent, expected)
|
|
53
|
+
|
|
54
|
+
def test_compact_number_expr_default(self):
|
|
55
|
+
expr = formatter.compact_number_expr()
|
|
56
|
+
self.assertEqual(expr, "replace(format(datum.value, '.3~s'), 'G', 'B')")
|
|
57
|
+
|
|
58
|
+
def test_compact_number_expr_params(self):
|
|
59
|
+
expr = formatter.compact_number_expr('other', 2)
|
|
60
|
+
self.assertEqual(expr, "replace(format(datum.other, '.2~s'), 'G', 'B')")
|
|
61
|
+
|
|
62
|
+
@parameterized.named_parameters(
|
|
63
|
+
('rounded_up_percent', 0.4257, 15, '42.6% (15)'),
|
|
64
|
+
('rounded_down_percent', 0.4251, 15, '42.5% (15)'),
|
|
65
|
+
('thousand_value', 0.42, 2e4, '42.0% (20k)'),
|
|
66
|
+
('million_value', 0.42, 3e7, '42.0% (30M)'),
|
|
67
|
+
('billion_value', 0.42, 4e9, '42.0% (4B)'),
|
|
68
|
+
)
|
|
69
|
+
def test_format_number_text_correct(self, percent, value, expected):
|
|
70
|
+
formatted_text = formatter.format_number_text(percent, value)
|
|
71
|
+
self.assertEqual(formatted_text, expected)
|
|
72
|
+
|
|
73
|
+
@parameterized.named_parameters(
|
|
74
|
+
('zero_precision_thousands', 12345, '$', '$12k'),
|
|
75
|
+
('round_up_thousands', 14900, '€', '€15k'),
|
|
76
|
+
('million_value', 3.21e6, '£', '£3.2M'),
|
|
77
|
+
('billion_value_round_up', 4.28e9, '¥', '¥4.3B'),
|
|
78
|
+
('negative', -12345, '₮', '-₮12k'),
|
|
79
|
+
)
|
|
80
|
+
def test_format_monetary_num_correct(self, num, currency, expected):
|
|
81
|
+
formatted_number = formatter.format_monetary_num(num, currency)
|
|
82
|
+
self.assertEqual(formatted_number, expected)
|
|
83
|
+
|
|
84
|
+
@parameterized.named_parameters(
|
|
85
|
+
('decimals', -0.1234, 2, '$', '-$0.12'),
|
|
86
|
+
('zero_precision_thousands', 12345, 0, '', '12k'),
|
|
87
|
+
('round_up_thousands', 14900, 0, '$', '$15k'),
|
|
88
|
+
('million_value', 3.21e6, 2, '$', '$3.21M'),
|
|
89
|
+
('negative', -12345, 0, '$', '-$12k'),
|
|
90
|
+
)
|
|
91
|
+
def test_compact_number_correct(self, num, precision, currency, expected):
|
|
92
|
+
formatted_number = formatter.compact_number(num, precision, currency)
|
|
93
|
+
self.assertEqual(formatted_number, expected)
|
|
94
|
+
|
|
95
|
+
def test_create_summary_html(self):
|
|
96
|
+
template_env = formatter.create_template_env()
|
|
97
|
+
title = 'Integration Test Report'
|
|
98
|
+
cards = ['<card>Card 1</card>', '<card>Card 2</card>']
|
|
99
|
+
|
|
100
|
+
html_result = formatter.create_summary_html(template_env, title, cards)
|
|
101
|
+
|
|
102
|
+
# Since summary.html contains DOCTYPE (which breaks ElementTree XML parser),
|
|
103
|
+
# we verify the output using string assertions.
|
|
104
|
+
self.assertIn('<!DOCTYPE html>', html_result)
|
|
105
|
+
self.assertIn(title, html_result)
|
|
106
|
+
self.assertIn('<card>Card 1</card>', html_result)
|
|
107
|
+
self.assertIn('<card>Card 2</card>', html_result)
|
|
108
|
+
|
|
109
|
+
def test_create_card_html_structure(self):
|
|
110
|
+
template_env = formatter.create_template_env()
|
|
111
|
+
card_spec = formatter.CardSpec(id='test_id', title='test_title')
|
|
112
|
+
stats_spec = formatter.StatsSpec(title='stats_title', stat='test_stat')
|
|
113
|
+
chart_spec = formatter.ChartSpec(
|
|
114
|
+
'test_chart_id', 'test_chart_json', 'test_chart_description'
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
card_html = ET.fromstring(
|
|
118
|
+
formatter.create_card_html(
|
|
119
|
+
template_env, card_spec, 'test_insights', [chart_spec], [stats_spec]
|
|
120
|
+
)
|
|
121
|
+
)
|
|
122
|
+
self.assertEqual(card_html.tag, 'card')
|
|
123
|
+
self.assertLen(card_html, 4)
|
|
124
|
+
self.assertEqual(card_html[0].tag, 'card-title')
|
|
125
|
+
self.assertEqual(card_html[1].tag, 'card-insights')
|
|
126
|
+
self.assertEqual(card_html[2].tag, 'stats-section')
|
|
127
|
+
self.assertEqual(card_html[3].tag, 'charts')
|
|
128
|
+
|
|
129
|
+
def test_create_card_html_text(self):
|
|
130
|
+
template_env = formatter.create_template_env()
|
|
131
|
+
card_spec = formatter.CardSpec(id='test_id', title='test_title')
|
|
132
|
+
chart_spec = formatter.ChartSpec(
|
|
133
|
+
'test_chart_id', 'test_chart_json', 'test_chart_description'
|
|
134
|
+
)
|
|
135
|
+
card_html = ET.fromstring(
|
|
136
|
+
formatter.create_card_html(
|
|
137
|
+
template_env, card_spec, 'test_insights', [chart_spec]
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
self.assertContainsSubset('test_title', card_html[0].text)
|
|
141
|
+
self.assertContainsSubset('test_insights', card_html[1][1].text)
|
|
142
|
+
|
|
143
|
+
def test_create_card_html_multiple_charts(self):
|
|
144
|
+
template_env = formatter.create_template_env()
|
|
145
|
+
card_spec = formatter.CardSpec(id='test_id', title='test_title')
|
|
146
|
+
chart_spec1 = formatter.ChartSpec(
|
|
147
|
+
'test_chart_id1', 'test_chart_json1', 'test_chart_description1'
|
|
148
|
+
)
|
|
149
|
+
chart_spec2 = formatter.ChartSpec(
|
|
150
|
+
'test_chart_id2', 'test_chart_json2', 'test_chart_description2'
|
|
151
|
+
)
|
|
152
|
+
card_html = ET.fromstring(
|
|
153
|
+
formatter.create_card_html(
|
|
154
|
+
template_env, card_spec, 'test_insights', [chart_spec1, chart_spec2]
|
|
155
|
+
)
|
|
156
|
+
)
|
|
157
|
+
charts = card_html[2]
|
|
158
|
+
self.assertLen(charts, 4) # Each chart has 2 items, chart and script.
|
|
159
|
+
|
|
160
|
+
def test_create_card_html_chart_structure(self):
|
|
161
|
+
template_env = formatter.create_template_env()
|
|
162
|
+
card_spec = formatter.CardSpec(id='test_id', title='test_title')
|
|
163
|
+
chart_spec = formatter.ChartSpec(
|
|
164
|
+
'test_chart_id', 'test_chart_json', 'test_chart_description'
|
|
165
|
+
)
|
|
166
|
+
card_html = ET.fromstring(
|
|
167
|
+
formatter.create_card_html(
|
|
168
|
+
template_env, card_spec, 'test_insights', [chart_spec]
|
|
169
|
+
)
|
|
170
|
+
)
|
|
171
|
+
chart_html = card_html[2]
|
|
172
|
+
self.assertEqual(chart_html.tag, 'charts')
|
|
173
|
+
self.assertEqual(chart_html[0].tag, 'chart')
|
|
174
|
+
self.assertEqual(chart_html[0][0].tag, 'chart-embed')
|
|
175
|
+
self.assertEqual(chart_html[0][1].tag, 'chart-description')
|
|
176
|
+
self.assertContainsSubset('test_chart_description', chart_html[0][1].text)
|
|
177
|
+
self.assertEqual(chart_html[1].tag, 'script')
|
|
178
|
+
self.assertContainsSubset('test_chart_json', chart_html[1].text)
|
|
179
|
+
|
|
180
|
+
def test_create_card_html_mulitple_stats(self):
|
|
181
|
+
template_env = formatter.create_template_env()
|
|
182
|
+
card_spec = formatter.CardSpec(id='test_id', title='test_title')
|
|
183
|
+
stat1 = formatter.StatsSpec(title='stats_title1', stat='test_stat1')
|
|
184
|
+
stat2 = formatter.StatsSpec(title='stats_title2', stat='test_stat2')
|
|
185
|
+
card_html = ET.fromstring(
|
|
186
|
+
formatter.create_card_html(
|
|
187
|
+
template_env, card_spec, 'test_insights', stats_specs=[stat1, stat2]
|
|
188
|
+
)
|
|
189
|
+
)
|
|
190
|
+
stats = card_html[2]
|
|
191
|
+
self.assertLen(stats, 2)
|
|
192
|
+
|
|
193
|
+
def test_create_card_html_stats_structure(self):
|
|
194
|
+
template_env = formatter.create_template_env()
|
|
195
|
+
card_spec = formatter.CardSpec(id='test_id', title='test_title')
|
|
196
|
+
stats_spec = formatter.StatsSpec(
|
|
197
|
+
title='stats_title', stat='test_stat', delta='+0.3'
|
|
198
|
+
)
|
|
199
|
+
card_html = ET.fromstring(
|
|
200
|
+
formatter.create_card_html(
|
|
201
|
+
template_env, card_spec, 'test_insights', stats_specs=[stats_spec]
|
|
202
|
+
)
|
|
203
|
+
)
|
|
204
|
+
stats_html = card_html[2]
|
|
205
|
+
self.assertEqual(stats_html.tag, 'stats-section')
|
|
206
|
+
self.assertEqual(stats_html[0].tag, 'stats')
|
|
207
|
+
self.assertEqual(stats_html[0][0].tag, 'stats-title')
|
|
208
|
+
self.assertEqual(stats_html[0][0].text, 'stats_title')
|
|
209
|
+
self.assertEqual(stats_html[0][1].tag, 'stat')
|
|
210
|
+
self.assertEqual(stats_html[0][1].text, 'test_stat')
|
|
211
|
+
self.assertEqual(stats_html[0][2].tag, 'delta')
|
|
212
|
+
self.assertContainsSubset('+0.3', stats_html[0][2].text)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
if __name__ == '__main__':
|
|
216
|
+
absltest.main()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
Copyright
|
|
2
|
+
Copyright 2025 Google LLC
|
|
3
3
|
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
you may not use this file except in compliance with the License.
|
|
@@ -42,7 +42,9 @@ limitations under the License.
|
|
|
42
42
|
</div>
|
|
43
43
|
</div>
|
|
44
44
|
|
|
45
|
-
{%
|
|
45
|
+
{% if start_date is defined and start_date %}
|
|
46
|
+
{% include "chips.html.jinja" %}
|
|
47
|
+
{% endif %}
|
|
46
48
|
|
|
47
49
|
<cards>
|
|
48
50
|
{# Each card is laid out in a grid. See; .card display layout. #}
|
meridian/version.py
CHANGED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Copyright 2025 The Meridian Authors.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""Generates Meridian Scenario Planner Dashboards in Looker Studio.
|
|
16
|
+
|
|
17
|
+
This package provides tools to create and manage Meridian dashboards. It helps
|
|
18
|
+
transform data from the MMM (Marketing Mix Modeling) schema into a custom
|
|
19
|
+
Looker Studio dashboard, which can be shared via a URL.
|
|
20
|
+
|
|
21
|
+
The typical workflow is:
|
|
22
|
+
|
|
23
|
+
1. Analyze MMM data into the appropriate schema.
|
|
24
|
+
2. Generate UI-specific proto messages from this data using
|
|
25
|
+
`mmm_ui_proto_generator`.
|
|
26
|
+
3. Build a Looker Studio URL that embeds this UI proto data using
|
|
27
|
+
`linkingapi`.
|
|
28
|
+
|
|
29
|
+
Key functionalities include:
|
|
30
|
+
|
|
31
|
+
- `linkingapi`: Builds Looker Studio report URLs with embedded data sources.
|
|
32
|
+
This allows for the creation of pre-configured reports.
|
|
33
|
+
- `mmm_ui_proto_generator`: Generates a `Mmm` proto message for the Meridian
|
|
34
|
+
Scenario Planner UI. It takes structured MMM data and transforms it into the
|
|
35
|
+
specific proto format that the dashboard frontend expects.
|
|
36
|
+
- `converters`: Provides utilities to convert and transform analyzed model
|
|
37
|
+
data into a data format that Looker Studio expects.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
from scenarioplanner import converters
|
|
41
|
+
from scenarioplanner import linkingapi
|
|
42
|
+
from scenarioplanner import mmm_ui_proto_generator
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Copyright 2025 The Meridian Authors.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""Provides tools for converting and wrapping MMM schema data.
|
|
16
|
+
|
|
17
|
+
This package contains modules to transform Marketing Mix Modeling (MMM) protocol
|
|
18
|
+
buffer data into other formats and provides high-level wrappers for easier data
|
|
19
|
+
manipulation, analysis, and reporting.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from scenarioplanner.converters import dataframe
|
|
23
|
+
from scenarioplanner.converters import mmm
|
|
24
|
+
from scenarioplanner.converters import mmm_converter
|
|
25
|
+
from scenarioplanner.converters import sheets
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Copyright 2025 The Meridian Authors.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""Converters for `Mmm` protos to flat dataframes.
|
|
16
|
+
|
|
17
|
+
This package provides a set of tools for transforming data from `Mmm`
|
|
18
|
+
protos into flat dataframes. This conversion makes the data easier to analyze,
|
|
19
|
+
visualize, and use in other data processing pipelines.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from scenarioplanner.converters.dataframe import budget_opt_converters
|
|
23
|
+
from scenarioplanner.converters.dataframe import common
|
|
24
|
+
from scenarioplanner.converters.dataframe import constants
|
|
25
|
+
from scenarioplanner.converters.dataframe import converter
|
|
26
|
+
from scenarioplanner.converters.dataframe import dataframe_model_converter
|
|
27
|
+
from scenarioplanner.converters.dataframe import marketing_analyses_converters
|
|
28
|
+
from scenarioplanner.converters.dataframe import rf_opt_converters
|