-
Notifications
You must be signed in to change notification settings - Fork 342
MMM Plot Suite Migration: arviz_plots Multi-Backend Support #2098
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already added claude commands and skills to the repo so it seems appropriate to add this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can it be renamed to AGENTS.md then if this if general enough then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Claude.md, like the skills and commands that were already uploaded, are used by Claude code. It expect for a with that name and these set of folders.
The text in Claude.md like the skills and command is very generic and can be used by any AI Platform, but we need this specific structure to get the most of Claude code.
So I don't think it make sense to change the name of this file while leaving all the .claude folder.
The current status of the repo is weird, we uploaded skills and command which mean we support Claude Code, but we are missing Claude.md, so Claude Code cannot run on this repo.
I think we should either go all-in and support claude code and add the Claude.md file, or remove the .claude folder. I prefer to add Claude.md
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2098 +/- ##
==========================================
+ Coverage 92.57% 92.65% +0.07%
==========================================
Files 69 71 +2
Lines 9430 9760 +330
==========================================
+ Hits 8730 9043 +313
- Misses 700 717 +17 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
cetagostini
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few docstrings changes.
pymc_marketing/mmm/plot.py
Outdated
| -------- | ||
| Basic usage: | ||
|
|
||
| >>> mmm.sample_posterior_predictive(X) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We avoid this and use code blocks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
pymc_marketing/mmm/plot.py
Outdated
| constant_data : xr.Dataset, optional | ||
| Dataset containing constant_data group. If None, uses self.idata.constant_data. | ||
|
|
||
| .. versionadded:: 0.18.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicated text?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I decided to simply remove all of these .. versionadded::. I don't think we need them here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can it be renamed to AGENTS.md then if this if general enough then.
| def test_legacy_plot_module_exists(): | ||
| """Test that legacy_plot module exists and can be imported.""" | ||
| try: | ||
| from pymc_marketing.mmm import legacy_plot | ||
|
|
||
| assert hasattr(legacy_plot, "LegacyMMMPlotSuite") | ||
| except ImportError as e: | ||
| pytest.fail(f"Failed to import legacy_plot: {e}") | ||
|
|
||
|
|
||
| def test_legacy_class_name(): | ||
| """Test that legacy suite class is named LegacyMMMPlotSuite.""" | ||
| from pymc_marketing.mmm.legacy_plot import LegacyMMMPlotSuite | ||
|
|
||
| assert LegacyMMMPlotSuite.__name__ == "LegacyMMMPlotSuite" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove. These tests will be obvious failures based on other tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
pymc_marketing/mmm/plot.py
Outdated
| def _resolve_backend(self, backend: str | None) -> str: | ||
| """Resolve backend parameter to actual backend string.""" | ||
| from pymc_marketing.mmm.config import mmm_config | ||
|
|
||
| return backend or mmm_config["plot.backend"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not toplevel import?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, agent generated code. I didn't catch it. fixed
| def test_contributions_over_time_accepts_data_parameter(mock_posterior_data): | ||
| """Test that contributions_over_time accepts data parameter.""" | ||
| # Create suite without idata | ||
| suite = MMMPlotSuite(idata=None) | ||
|
|
||
| # Should work with explicit data parameter | ||
| pc = suite.contributions_over_time(var=["intercept"], data=mock_posterior_data) | ||
|
|
||
| assert isinstance(pc, arviz_plots.PlotCollection) | ||
|
|
||
|
|
||
| def test_contributions_over_time_data_parameter_fallback(mock_idata_with_posterior): | ||
| """Test that contributions_over_time falls back to self.idata.posterior.""" | ||
| suite = MMMPlotSuite(idata=mock_idata_with_posterior) | ||
|
|
||
| # Should work without data parameter (fallback) | ||
| pc = suite.contributions_over_time(var=["intercept"]) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot use pytest.mark.parametrize to combine these two tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these are fine to keep separated.
|
@williambdean I've opened a new pull request, #2103, to work on those changes. Once the pull request is ready, I'll request review from you. |
| raise NotImplementedError( | ||
| "budget_allocation() was removed in MMMPlotSuite v2.\n\n" | ||
| "The new arviz_plots-based implementation doesn't support this chart type.\n\n" | ||
| "Alternatives:\n" | ||
| " 1. For ROI distributions: use budget_allocation_roas()\n" | ||
| " 2. To use old method: set mmm_config['plot.use_v2'] = False\n" | ||
| " 3. Implement custom bar chart using the samples data\n\n" | ||
| "See documentation: https://docs.pymc-marketing.io/en/latest/mmm/plotting_migration.html#budget-allocation" | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the goal to remove these missing methods entirely in 0.20.0 ? Or will they only exist for the matplotlib backend ?
CC: @cetagostini
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've consulted with @cetagostini regarding this change, and followed his recommendation.
His point was that the current implementation of this graph is not the best, and so we decided to create budget_allocation_roas and deprecated budget_allocation entirely.
in 0.20.0 we will remove LegacyMMMPlotSuite and only the new suite will be available.
|
@williambdean @cetagostini |
* Initial plan * Combine contributions_over_time tests using pytest.mark.parametrize Co-authored-by: williambdean <57733339+williambdean@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: williambdean <57733339+williambdean@users.noreply.github.com> Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
MMM Plot Suite Migration: arviz_plots Multi-Backend Support
Summary
This PR introduces a new version of
MMMPlotSuitebuilt onarviz_plots, enabling multi-backend plotting (matplotlib, plotly, bokeh) while preserving full backward compatibility. The original matplotlib-only implementation is preserved asLegacyMMMPlotSuiteand remains the default in v0.18.0, with users able to opt into the new suite via configuration.This closes #2083 and #2081 (duplicated).
Key highlights:
LegacyMMMPlotSuiteKey Changes
🎨 New Multi-Backend Plotting Suite (
plot.py)Complete rewrite of
MMMPlotSuiteusing arviz_plots:PlotCollectionobjects instead of(Figure, Axes)tuplesposterior_predictive()- Posterior predictive time seriescontributions_over_time()- Variable contributions over time with HDIsaturation_scatterplot()- Channel saturation scatter plotssaturation_curves()- Saturation curves with samples and HDI overlaysbudget_allocation_roas()- Budget allocation ROAS distributionsallocated_contribution_by_channel_over_time()- Allocated contributionssensitivity_analysis()- Sensitivity analysis resultsuplift_curve()- Uplift curvesmarginal_curve()- Marginal effectsArchitectural improvements:
dataparameters with fallback toself.idata_resolve_backend()handles global config with per-method override_init_subplots(),_build_subplot_title(),_add_median_and_hdi()🔄 Backward Compatibility & Legacy Suite
Legacy Suite Created (
legacy_plot.py, 1,937 lines):LegacyMMMPlotSuiteVersion Switching (
multidimensional.py):Modified
MMM.plotproperty to support version control:Deprecation Timeline:
⚙️ Configuration System (
config.py- NEW)Added global MMM configuration (156 lines):
Features:
rcParamspatternbackendparameter on all plot methodspymc_marketing.mmmfor easy access📊 API Improvements
self.idatacontributions_over_time(data=...)saturation_scatterplot(constant_data=..., posterior_data=...)saturation_curves(constant_data=..., posterior_data=...)sensitivity_analysis(data=...),uplift_curve(data=...),marginal_curve(data=...)🧪 Comprehensive Testing (~3,100 lines of test code)
New Test Files:
tests/mmm/conftest.py(307 lines): Shared fixtures for all plotting teststests/mmm/test_plot.py(1,719 lines): Rewritten for new suitetests/mmm/test_legacy_plot.py(1,054 lines): Full legacy suite coveragetests/mmm/test_plot_compatibility.py(475 lines): Version switching testsmmm_config["plot.use_v2"]switchingtests/mmm/test_plot_data_parameters.py(120 lines): Data parameter validationtests/mmm/test_legacy_plot_imports.py(33 lines): Import validationtests/mmm/test_legacy_plot_regression.py(56 lines): Legacy behavior regression testsBreaking Changes
Return Types
Legacy (matplotlib-only):
New (multi-backend):
Parameter Changes
posterior_predictive(var=...): Now acceptsstrinstead oflist[str](call multiple times for multiple variables)ax,figsize,colors,subplot_kwargs,rc_paramsparameters (usePlotCollectionAPI instead)backendparameter for per-method overrideMethod Changes
budget_allocation(): Now a deprecated wrapper that callsbudget_allocation_roas()with deprecation warningbudget_allocation_roas(): New primary method for budget allocation visualizationsMigration Guide
Quick Start
Opting Out (Temporary)
Files Changed
Statistics: 15 files changed, 9,092 insertions(+), 1,886 deletions(-)
New Files
pymc_marketing/mmm/config.py(156 lines)pymc_marketing/mmm/legacy_plot.py(1,937 lines)tests/mmm/conftest.py(307 lines)tests/mmm/test_legacy_plot.py(1,054 lines)tests/mmm/test_legacy_plot_imports.py(33 lines)tests/mmm/test_legacy_plot_regression.py(56 lines)tests/mmm/test_plot_compatibility.py(475 lines)tests/mmm/test_plot_data_parameters.py(120 lines)CLAUDE.md(272 lines)Modified Files
pymc_marketing/mmm/__init__.py(+2 lines: exportmmm_config)pymc_marketing/mmm/plot.py(complete rewrite: ~2660 lines changed)pymc_marketing/mmm/multidimensional.py(+54 lines: version control logic)tests/mmm/test_plot.py(heavily rewritten: 1719 lines).gitignore(+3 lines)CLAUDE.md(NEW, 272 lines: project documentation)Testing
Documentation
CLAUDE.md: Added comprehensive MMM plotting architecture documentationconfig.py: Extensive docstrings with usage examplesPlotCollectionreturn typesbackendparameter documentation.. versionadded::,.. versionchanged::)Timeline
plot.use_v2 = True)Checklist
Notes
mmm_config["plot.use_v2"] = Truegit log --follow)📚 Documentation preview 📚: https://pymc-marketing--2098.org.readthedocs.build/en/2098/