Add designed-mode panel comparison (factorial ANOVA + Tukey/Dunnett post-hoc)#471
Merged
Merged
Conversation
…ost-hoc New module process_improve.sensory.designed complements the observational relate with the designed-mode question: which product treatments differ, and by how much, on each attribute, for a randomized complete block design (the same panelists score every treatment, panelist as the block). Public API (generic in the factor column names): - factorial_anova: per-attribute Type III factorial ANOVA (score ~ C(factor_1) * C(factor_2) * ... + C(block)), handling unbalanced grids and testing factor-by-factor interactions. - tukey_hsd: all-pairwise Tukey HSD off the blocked-model error mean square and the studentized-range distribution, with a compact-letter display. - dunnett_vs_control: Dunnett two-sided test of each treatment vs one control. - compare_products: orchestrates the ANOVA + post-hoc tests and returns a ComparisonResult; a within= argument runs simple-effects post-hoc within each level of another factor. Built on the existing statsmodels/patsy/scipy dependencies (no new deps). Tests in tests/test_sensory_designed.py drive a synthetic RCBD with planted effects and cross-check the Tukey maths against scipy.stats.tukey_hsd. Version bump 1.58.0 -> 1.59.0 with matching CITATION.cff and CHANGELOG entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Ra2KAdJeGtnUzi68yDFaR
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
…xample Add a "Comparing designed treatments" section to the sensory panel user guide covering compare_products / factorial_anova / tukey_hsd / dunnett_vs_control, the randomized-complete-block model, and a worked numerical example that shows Tukey and Dunnett reaching different (both correct) verdicts on the same treatment-vs-control comparison. Cross-linked from the designed-versus- observational section. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Ra2KAdJeGtnUzi68yDFaR
ruff 0.16 promoted several rules into the select=["ALL"] set (CPY001, PLR0917, and others) that fire across the existing code base, turning the lint job red on every branch. Cap the dev dependency at ruff>=0.11.0,<0.16 (resolves to 0.15.22) so `ruff check .` passes again; the new rules can be triaged separately before lifting the cap. Version bump 1.59.0 -> 1.59.1 with matching CITATION.cff and CHANGELOG entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Ra2KAdJeGtnUzi68yDFaR
…y-analysis-lrk3u0 # Conflicts: # CHANGELOG.md # CITATION.cff # pyproject.toml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
process_improve.sensory.designed: the designed-mode complement to the observational relate, answering "which product treatments differ, and by how much, on each attribute" for a randomized complete block design (the same panelists score every treatment, panelist as the block). The sensory roadmap listed Tukey/LSD post-hoc as a planned item; this fills that gap.factorial_anova(per-attribute Type III factorial ANOVAscore ~ C(f1) * C(f2) * ... + C(block), handling unbalanced grids and factor-by-factor interactions),tukey_hsd(all-pairwise Tukey HSD off the blocked-model error mean square and the studentized-range distribution, with a compact-letter display),dunnett_vs_control(Dunnett two-sided vs one control), andcompare_products(orchestrator returning aComparisonResult; awithin=argument runs simple-effects post-hoc within each level of another factor, the right follow-up once an interaction is significant).statsmodels/patsy/scipyruntime dependencies; no new dependency added.Test plan
uv run pytest tests/test_sensory_designed.py --no-cov(11 tests): a synthetic RCBD with planted effects (one high formulation, aging main effect, a formulation-by-condition interaction that collapses one treatment only under one condition) checked against the ANOVA F-tests, Tukey groupings, Dunnett flags and letter display.tukey_hsdp-values matchscipy.stats.tukey_hsdon a balanced one-way case to 1e-6.tests/test_sensory.py,test_sensory_end_to_end.py,test_sensory_designed.py): 69 passed.uv run mypy src/process_improve/sensory/designed.pyclean;ruff checkclean on the new files (project config).Checklist
pyproject.toml(MINOR: new module / API additions),1.58.0->1.59.0ruff check .passesCHANGELOG.mdupdated (andCITATION.cffversion synced)Generated by Claude Code