DaSPi 2.1.0__tar.gz → 2.3.0__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 (182) hide show
  1. {daspi-2.1.0 → daspi-2.3.0}/PKG-INFO +2 -2
  2. daspi-2.3.0/daspi/__init__.py +315 -0
  3. {daspi-2.1.0 → daspi-2.3.0}/daspi/_typing.py +11 -0
  4. {daspi-2.1.0 → daspi-2.3.0}/daspi/anova/model.py +113 -33
  5. {daspi-2.1.0 → daspi-2.3.0}/daspi/anova/tables.py +16 -2
  6. {daspi-2.1.0 → daspi-2.3.0}/daspi/constants.py +1 -1
  7. {daspi-2.1.0 → daspi-2.3.0}/daspi/plotlib/chart.py +9 -4
  8. {daspi-2.1.0 → daspi-2.3.0}/daspi/plotlib/facets.py +2 -1
  9. {daspi-2.1.0 → daspi-2.3.0}/daspi/plotlib/plotter.py +547 -110
  10. {daspi-2.1.0 → daspi-2.3.0}/daspi/plotlib/precast.py +2 -1
  11. {daspi-2.1.0 → daspi-2.3.0}/daspi/statistics/estimation.py +128 -12
  12. {daspi-2.1.0 → daspi-2.3.0}/pyproject.toml +1 -1
  13. {daspi-2.1.0 → daspi-2.3.0}/tests/anova_model_test.py +22 -2
  14. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Formatting_Features_Test_alignments_basic.png +0 -0
  15. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Formatting_Features_Test_all_alignments.png +0 -0
  16. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Formatting_Features_Test_angles_basic.png +0 -0
  17. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Formatting_Features_Test_callable_formatters.png +0 -0
  18. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Formatting_Features_Test_combined_all_features.png +0 -0
  19. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Formatting_Features_Test_extreme_angles.png +0 -0
  20. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Formatting_Features_Test_formatters_basic.png +0 -0
  21. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Formatting_Features_Test_formatters_scientific.png +0 -0
  22. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Formatting_Features_Test_multivariate_formatting.png +0 -0
  23. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Formatting_Features_Test_orientation_mapping.png +0 -0
  24. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Formatting_Features_Test_percentage_formatter.png +0 -0
  25. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/GaussianKDEContourUnivariate_comparison_with_violin.png +0 -0
  26. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/GaussianKDEContourUnivariate_custom_color.png +0 -0
  27. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/GaussianKDEContourUnivariate_custom_width.png +0 -0
  28. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/GaussianKDEContourUnivariate_joint_chart_mixed_plots.png +0 -0
  29. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/GaussianKDEContourUnivariate_multivariate_chart_facets.png +0 -0
  30. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/GaussianKDEContourUnivariate_resolution_high.png +0 -0
  31. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/GaussianKDEContourUnivariate_single_chart_horizontal.png +0 -0
  32. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/GaussianKDEContourUnivariate_single_chart_no_fade.png +0 -0
  33. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/GaussianKDEContourUnivariate_single_chart_no_fill.png +0 -0
  34. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/GaussianKDEContourUnivariate_single_chart_simple.png +0 -0
  35. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/GaussianKDEContourUnivariate_single_chart_with_hue.png +0 -0
  36. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/JointChart_bar_stacking.png +0 -0
  37. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/JointChart_pareto_marked.png +0 -0
  38. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/JointChart_probability_dists-prob.png +0 -0
  39. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/JointChart_regression_kde.png +0 -0
  40. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/MultivariateChart_full-stripes.png +0 -0
  41. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/MultivariateChart_full.png +0 -0
  42. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Precasts_bivariate-univariate-charts_contour-mean-test.png +0 -0
  43. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Precasts_bivariate-univariate-charts_mean-test.png +0 -0
  44. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Precasts_bivariate-univariate-charts_simple.png +0 -0
  45. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Precasts_bivariate-univariate-charts_smoothed.png +0 -0
  46. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Precasts_bivariate-univariate-charts_user.png +0 -0
  47. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Precasts_pair_comparison_charts_basic.png +0 -0
  48. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Precasts_parameter_relevance_charts_basic.png +0 -0
  49. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Precasts_process-capabity-analysis-charts_hue.png +0 -0
  50. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Precasts_residual_charts_basic.png +0 -0
  51. daspi-2.3.0/tests/charts/SingleChart_KDE-cumulative_multiple.png +0 -0
  52. daspi-2.3.0/tests/charts/SingleChart_KDE-cumulative_simple.png +0 -0
  53. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_KDE_multiple.png +0 -0
  54. daspi-2.3.0/tests/charts/SingleChart_KDE_ridge.png +0 -0
  55. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_beeswarm_multiple.png +0 -0
  56. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_beeswarm_simple.png +0 -0
  57. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_blandaltman_simple.png +0 -0
  58. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_blandaltman_user.png +0 -0
  59. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_box_fill.png +0 -0
  60. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_box_multiple.png +0 -0
  61. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_box_simple.png +0 -0
  62. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_categorical-float-features_simple.png +0 -0
  63. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_errorbar_mean-test.png +0 -0
  64. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_errorbar_sem.png +0 -0
  65. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_errorbar_std-test.png +0 -0
  66. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_errorbar_var-test.png +0 -0
  67. daspi-2.3.0/tests/charts/SingleChart_fitted-density_cdf-multiple.png +0 -0
  68. daspi-2.3.0/tests/charts/SingleChart_fitted-density_pdf-data.png +0 -0
  69. daspi-2.3.0/tests/charts/SingleChart_fitted-density_pdf-norm.png +0 -0
  70. daspi-2.3.0/tests/charts/SingleChart_jitter_multiple.png +0 -0
  71. daspi-2.3.0/tests/charts/SingleChart_jitter_simple.png +0 -0
  72. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_line_hue.png +0 -0
  73. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_line_hue_size.png +0 -0
  74. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_pareto_simple.png +0 -0
  75. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_pareto_transposed.png +0 -0
  76. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_quantiles_multiple.png +0 -0
  77. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_quantiles_simple.png +0 -0
  78. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_scatter_full.png +0 -0
  79. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_scatter_hue-shape.png +0 -0
  80. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_scatter_hue-size.png +0 -0
  81. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_scatter_hue.png +0 -0
  82. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_scatter_shape.png +0 -0
  83. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_scatter_size-shape.png +0 -0
  84. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_scatter_size.png +0 -0
  85. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_violin_mono.png +0 -0
  86. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_violin_multiple.png +0 -0
  87. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_violin_simple.png +0 -0
  88. {daspi-2.1.0 → daspi-2.3.0}/tests/plotlib_plotter_test.py +191 -1
  89. {daspi-2.1.0 → daspi-2.3.0}/tests/plotlib_visual_test.py +171 -1
  90. {daspi-2.1.0 → daspi-2.3.0}/tests/statistics_estimation_test.py +110 -1
  91. daspi-2.1.0/daspi/__init__.py +0 -175
  92. daspi-2.1.0/tests/charts/SingleChart_jitter_multiple.png +0 -0
  93. daspi-2.1.0/tests/charts/SingleChart_jitter_simple.png +0 -0
  94. {daspi-2.1.0 → daspi-2.3.0}/LICENSE +0 -0
  95. {daspi-2.1.0 → daspi-2.3.0}/README.md +0 -0
  96. {daspi-2.1.0 → daspi-2.3.0}/daspi/_version.py +0 -0
  97. {daspi-2.1.0 → daspi-2.3.0}/daspi/anova/__init__.py +0 -0
  98. {daspi-2.1.0 → daspi-2.3.0}/daspi/anova/convert.py +0 -0
  99. {daspi-2.1.0 → daspi-2.3.0}/daspi/config.py +0 -0
  100. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/__init__.py +0 -0
  101. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/ancova.csv +0 -0
  102. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/anova.csv +0 -0
  103. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/anova2.csv +0 -0
  104. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/anova2_unbalanced.csv +0 -0
  105. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/anova3.csv +0 -0
  106. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/anova3_unbalanced.csv +0 -0
  107. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/carpet_full-factorial.csv +0 -0
  108. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/covariate.csv +0 -0
  109. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/drop_card.csv +0 -0
  110. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/eeprom_full-factorial.csv +0 -0
  111. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/eeprom_partial-factorial.csv +0 -0
  112. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/grnr_adjustment.csv +0 -0
  113. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/grnr_layer_thickness.csv +0 -0
  114. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/grnr_spc.csv +0 -0
  115. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/iris.csv +0 -0
  116. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/mpg.csv +0 -0
  117. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/painkillers-dissolution.csv +0 -0
  118. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/partial_factorial.csv +0 -0
  119. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/penguins.csv +0 -0
  120. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/process_capability.mpx +0 -0
  121. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/salt_sticks.csv +0 -0
  122. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/shoe-sole.csv +0 -0
  123. {daspi-2.1.0 → daspi-2.3.0}/daspi/datasets/tips.csv +0 -0
  124. {daspi-2.1.0 → daspi-2.3.0}/daspi/doe/__init__.py +0 -0
  125. {daspi-2.1.0 → daspi-2.3.0}/daspi/doe/build.py +0 -0
  126. {daspi-2.1.0 → daspi-2.3.0}/daspi/plotlib/__init__.py +0 -0
  127. {daspi-2.1.0 → daspi-2.3.0}/daspi/plotlib/appearance.py +0 -0
  128. {daspi-2.1.0 → daspi-2.3.0}/daspi/plotlib/classify.py +0 -0
  129. {daspi-2.1.0 → daspi-2.3.0}/daspi/plotlib/styles/daspi-dark.mplstyle +0 -0
  130. {daspi-2.1.0 → daspi-2.3.0}/daspi/plotlib/styles/daspi.mplstyle +0 -0
  131. {daspi-2.1.0 → daspi-2.3.0}/daspi/plotlib/styles/ggplot2.mplstyle +0 -0
  132. {daspi-2.1.0 → daspi-2.3.0}/daspi/plotlib/styles/seaborn.mplstyle +0 -0
  133. {daspi-2.1.0 → daspi-2.3.0}/daspi/requirements.txt +0 -0
  134. {daspi-2.1.0 → daspi-2.3.0}/daspi/statistics/__init__.py +0 -0
  135. {daspi-2.1.0 → daspi-2.3.0}/daspi/statistics/confidence.py +0 -0
  136. {daspi-2.1.0 → daspi-2.3.0}/daspi/statistics/hypothesis.py +0 -0
  137. {daspi-2.1.0 → daspi-2.3.0}/daspi/statistics/montecarlo.py +0 -0
  138. {daspi-2.1.0 → daspi-2.3.0}/daspi/strings.py +0 -0
  139. {daspi-2.1.0 → daspi-2.3.0}/tests/ANOVA_SS_Fehler.mpx +0 -0
  140. {daspi-2.1.0 → daspi-2.3.0}/tests/ANOVA_SS_Fehler.mpx.bak +0 -0
  141. {daspi-2.1.0 → daspi-2.3.0}/tests/GageRnR.mpx +0 -0
  142. {daspi-2.1.0 → daspi-2.3.0}/tests/GageRnR.mpx.bak +0 -0
  143. {daspi-2.1.0 → daspi-2.3.0}/tests/__init__.py +0 -0
  144. {daspi-2.1.0 → daspi-2.3.0}/tests/anova_convert_test.py +0 -0
  145. {daspi-2.1.0 → daspi-2.3.0}/tests/anova_tables_test.py +0 -0
  146. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/JointChart_kdes_kde-mean.png +0 -0
  147. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/JointChart_kdes_mixed-kde.png +0 -0
  148. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/JointChart_probability_norm-prob.png +0 -0
  149. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Precasts_gage_rnr_model_basic.png +0 -0
  150. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/Precasts_gage_study_model_basic.png +0 -0
  151. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_KDE_simple.png +0 -0
  152. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_scatter_simple-stripes-65ci.png +0 -0
  153. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_scatter_simple-stripes-99ci.png +0 -0
  154. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_scatter_simple-stripes.png +0 -0
  155. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_scatter_simple.png +0 -0
  156. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_scatter_transposed.png +0 -0
  157. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_violine-contour_simple.png +0 -0
  158. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_violine_mono.png +0 -0
  159. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_violine_multiple.png +0 -0
  160. {daspi-2.1.0 → daspi-2.3.0}/tests/charts/SingleChart_violine_simple.png +0 -0
  161. {daspi-2.1.0 → daspi-2.3.0}/tests/config_test.py +0 -0
  162. {daspi-2.1.0 → daspi-2.3.0}/tests/data/anova3_result.csv +0 -0
  163. {daspi-2.1.0 → daspi-2.3.0}/tests/data/dists_10-samples.csv +0 -0
  164. {daspi-2.1.0 → daspi-2.3.0}/tests/data/dists_25-samples.csv +0 -0
  165. {daspi-2.1.0 → daspi-2.3.0}/tests/data/gage_rnr.csv +0 -0
  166. {daspi-2.1.0 → daspi-2.3.0}/tests/data/gage_study.csv +0 -0
  167. {daspi-2.1.0 → daspi-2.3.0}/tests/data/generate_dists.py +0 -0
  168. {daspi-2.1.0 → daspi-2.3.0}/tests/data/grnr_d-optimal.csv +0 -0
  169. {daspi-2.1.0 → daspi-2.3.0}/tests/data/uncertainties.csv +0 -0
  170. {daspi-2.1.0 → daspi-2.3.0}/tests/doe_build_test.py +0 -0
  171. {daspi-2.1.0 → daspi-2.3.0}/tests/plotlib_appearance_test.py +0 -0
  172. {daspi-2.1.0 → daspi-2.3.0}/tests/plotlib_chart_test.py +0 -0
  173. {daspi-2.1.0 → daspi-2.3.0}/tests/plotlib_classify_test.py +0 -0
  174. {daspi-2.1.0 → daspi-2.3.0}/tests/plotlib_facets_test.py +0 -0
  175. {daspi-2.1.0 → daspi-2.3.0}/tests/plotlib_templates_test.py +0 -0
  176. {daspi-2.1.0 → daspi-2.3.0}/tests/r2_pred.mpx +0 -0
  177. {daspi-2.1.0 → daspi-2.3.0}/tests/r2_pred.mpx.bak +0 -0
  178. {daspi-2.1.0 → daspi-2.3.0}/tests/statistics_confidence_test.py +0 -0
  179. {daspi-2.1.0 → daspi-2.3.0}/tests/statistics_hypothesis_test.py +0 -0
  180. {daspi-2.1.0 → daspi-2.3.0}/tests/statistics_montecarlo_test.py +0 -0
  181. {daspi-2.1.0 → daspi-2.3.0}/tests/strings_test.py +0 -0
  182. {daspi-2.1.0 → daspi-2.3.0}/tests/test_full_factorial_design_builder.py +0 -0
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: DaSPi
3
- Version: 2.1.0
3
+ Version: 2.3.0
4
4
  Summary: Visualize and analyze your data with DaSPi. This package is designed for users who want to find relevant influencing factors in processes and validate improvements.
5
- Author-Email: =?utf-8?q?Reto_J=C3=A4ggli?= <reto@jaeggli.email>
5
+ Author-Email: Reto Jäggli <reto@jaeggli.email>
6
6
  License: MIT
7
7
  Project-URL: Repository, https://github.com/j4ggr/DaSPi
8
8
  Project-URL: Documentation, https://j4ggr.github.io/DaSPi/
@@ -0,0 +1,315 @@
1
+ """
2
+ DaSPi — Process Analytics & Six Sigma in Python
3
+
4
+ DaSPi helps engineers analyze and improve processes using statistical workflows.
5
+
6
+ ## Four Flagship Workflows
7
+
8
+ 1. **Gage R&R Analysis** — Verify measurement system capability (MSA Type 1 & 2)
9
+ 2. **Process Capability Analysis** — Evaluate if process meets specifications (Cp, Cpk)
10
+ 3. **Root Cause Analysis** — Identify factors that drive variation (ANOVA, regression)
11
+ 4. **Statistical Process Control** — Monitor process stability (SPC charts)
12
+
13
+ Each workflow produces visual output + interpretation in under 20 lines of code.
14
+
15
+ For detailed examples and documentation, visit: https://j4ggr.github.io/DaSPi/
16
+ """
17
+
18
+ from ._version import __version__
19
+ from .anova.convert import frames_to_html, get_term_name
20
+ from .anova.model import (
21
+ GageRnRModel,
22
+ GageStudyModel,
23
+ GeneralizedLinearModel,
24
+ LinearModel,
25
+ hierarchical,
26
+ is_main_parameter,
27
+ )
28
+ from .anova.tables import (
29
+ anova_table,
30
+ terms_effect,
31
+ terms_probability,
32
+ uniques,
33
+ variance_inflation_factor,
34
+ )
35
+ from .config import CONFIG
36
+ from .constants import (
37
+ ANOVA,
38
+ CATEGORY,
39
+ COLOR,
40
+ DEFAULT,
41
+ DIST,
42
+ KW,
43
+ LABEL,
44
+ LINE,
45
+ PLOTTER,
46
+ RE,
47
+ SIGMA_DIFFERENCE,
48
+ )
49
+ from .datasets import list_dataset, load_dataset
50
+ from .doe import (
51
+ Factor,
52
+ FractionalFactorialDesignBuilder,
53
+ FullFactorial2kDesignBuilder,
54
+ FullFactorialDesignBuilder,
55
+ get_default_generators,
56
+ )
57
+ from .plotlib import style
58
+ from .plotlib.chart import Chart, JointChart, MultivariateChart, SingleChart
59
+ from .plotlib.classify import Dodger, HueLabel, ShapeLabel, SizeLabel
60
+ from .plotlib.facets import AxesFacets, LabelFacets, StripesFacets, flat_unique
61
+ from .plotlib.plotter import (
62
+ Bar,
63
+ Beeswarm,
64
+ BlandAltman,
65
+ Box,
66
+ CapabilityConfidenceInterval,
67
+ CategoricalObservation,
68
+ CenterLocation,
69
+ ConfidenceInterval,
70
+ DensityCurve,
71
+ ErrorBar,
72
+ FittedDensity,
73
+ GaussianKDE,
74
+ GaussianKDEContour,
75
+ GaussianKDEContourUnivariate,
76
+ HideSubplot,
77
+ Jitter,
78
+ Line,
79
+ LinearRegressionLine,
80
+ LoessLine,
81
+ MeanTest,
82
+ ParallelCoordinate,
83
+ Pareto,
84
+ Plotter,
85
+ Probability,
86
+ ProportionTest,
87
+ QuantileBoxes,
88
+ Scatter,
89
+ SkipSubplot,
90
+ SpreadWidth,
91
+ StandardErrorMean,
92
+ Stem,
93
+ StripeLine,
94
+ StripeSpan,
95
+ TransformPlotter,
96
+ VariationTest,
97
+ Violin,
98
+ )
99
+ from .plotlib.precast import (
100
+ BivariateUnivariateCharts,
101
+ GageRnRCharts,
102
+ GageStudyCharts,
103
+ PairComparisonCharts,
104
+ PairwiseMatrixCharts,
105
+ ParameterRelevanceCharts,
106
+ ProcessCapabilityAnalysisCharts,
107
+ ResidualsCharts,
108
+ )
109
+ from .statistics.confidence import (
110
+ bonferroni_ci,
111
+ confidence_to_alpha,
112
+ cp_ci,
113
+ cpk_ci,
114
+ delta_mean_ci,
115
+ delta_proportions_ci,
116
+ delta_stdev_ci,
117
+ delta_variance_ci,
118
+ fit_ci,
119
+ mean_ci,
120
+ median_ci,
121
+ prediction_ci,
122
+ proportion_ci,
123
+ sem,
124
+ stdev_ci,
125
+ variance_ci,
126
+ )
127
+ from .statistics.estimation import (
128
+ DistributionEstimator,
129
+ GageEstimator,
130
+ LocationDispersionEstimator,
131
+ Loess,
132
+ Lowess,
133
+ MeasurementUncertainty,
134
+ ProcessEstimator,
135
+ estimate_capability_confidence,
136
+ estimate_distribution,
137
+ estimate_kernel_density,
138
+ estimate_kernel_density_2d,
139
+ estimate_probability_density,
140
+ estimate_resolution,
141
+ root_sum_squares,
142
+ )
143
+ from .statistics.hypothesis import (
144
+ all_normal,
145
+ anderson_darling_test,
146
+ dunn_test,
147
+ f_test,
148
+ kolmogorov_smirnov_test,
149
+ kurtosis_test,
150
+ levene_test,
151
+ mean_stability_test,
152
+ pairwise_tests,
153
+ position_test,
154
+ proportions_test,
155
+ skew_test,
156
+ t_test,
157
+ variance_stability_test,
158
+ variance_test,
159
+ )
160
+ from .statistics.montecarlo import (
161
+ UNBOUNDED,
162
+ Binning,
163
+ RandomProcessValue,
164
+ Specification,
165
+ SpecLimits,
166
+ inclination_displacement,
167
+ round_to_nearest,
168
+ )
169
+ from .strings import STR
170
+
171
+ __all__ = [
172
+ 'ANOVA',
173
+ 'CATEGORY',
174
+ 'COLOR',
175
+ 'CONFIG',
176
+ 'DEFAULT',
177
+ 'DIST',
178
+ 'KW',
179
+ 'LABEL',
180
+ 'LINE',
181
+ 'PLOTTER',
182
+ 'RE',
183
+ 'SIGMA_DIFFERENCE',
184
+ 'STR',
185
+ 'UNBOUNDED',
186
+ 'AxesFacets',
187
+ 'Bar',
188
+ 'Beeswarm',
189
+ 'Binning',
190
+ 'BivariateUnivariateCharts',
191
+ 'BlandAltman',
192
+ 'Box',
193
+ 'CapabilityConfidenceInterval',
194
+ 'CategoricalObservation',
195
+ 'CenterLocation',
196
+ 'Chart',
197
+ 'ConfidenceInterval',
198
+ 'DensityCurve',
199
+ 'DistributionEstimator',
200
+ 'Dodger',
201
+ 'ErrorBar',
202
+ 'Factor',
203
+ 'FittedDensity',
204
+ 'FractionalFactorialDesignBuilder',
205
+ 'FullFactorial2kDesignBuilder',
206
+ 'FullFactorialDesignBuilder',
207
+ 'GageEstimator',
208
+ 'GageRnRCharts',
209
+ 'GageRnRModel',
210
+ 'GageStudyCharts',
211
+ 'GageStudyModel',
212
+ 'GaussianKDE',
213
+ 'GaussianKDEContour',
214
+ 'GaussianKDEContourUnivariate',
215
+ 'GeneralizedLinearModel',
216
+ 'HideSubplot',
217
+ 'HueLabel',
218
+ 'Jitter',
219
+ 'JointChart',
220
+ 'LabelFacets',
221
+ 'Line',
222
+ 'LinearModel',
223
+ 'LinearRegressionLine',
224
+ 'LocationDispersionEstimator',
225
+ 'Loess',
226
+ 'LoessLine',
227
+ 'Lowess',
228
+ 'MeanTest',
229
+ 'MeasurementUncertainty',
230
+ 'MultivariateChart',
231
+ 'PairComparisonCharts',
232
+ 'PairwiseMatrixCharts',
233
+ 'ParallelCoordinate',
234
+ 'ParameterRelevanceCharts',
235
+ 'Pareto',
236
+ 'Plotter',
237
+ 'Probability',
238
+ 'ProcessCapabilityAnalysisCharts',
239
+ 'ProcessEstimator',
240
+ 'ProportionTest',
241
+ 'QuantileBoxes',
242
+ 'RandomProcessValue',
243
+ 'ResidualsCharts',
244
+ 'Scatter',
245
+ 'ShapeLabel',
246
+ 'SingleChart',
247
+ 'SizeLabel',
248
+ 'SkipSubplot',
249
+ 'SpecLimits',
250
+ 'Specification',
251
+ 'SpreadWidth',
252
+ 'StandardErrorMean',
253
+ 'Stem',
254
+ 'StripeLine',
255
+ 'StripeSpan',
256
+ 'StripesFacets',
257
+ 'TransformPlotter',
258
+ 'VariationTest',
259
+ 'Violin',
260
+ '__version__',
261
+ 'all_normal',
262
+ 'anderson_darling_test',
263
+ 'anova_table',
264
+ 'bonferroni_ci',
265
+ 'confidence_to_alpha',
266
+ 'cp_ci',
267
+ 'cpk_ci',
268
+ 'delta_mean_ci',
269
+ 'delta_proportions_ci',
270
+ 'delta_stdev_ci',
271
+ 'delta_variance_ci',
272
+ 'dunn_test',
273
+ 'estimate_capability_confidence',
274
+ 'estimate_distribution',
275
+ 'estimate_kernel_density',
276
+ 'estimate_kernel_density_2d',
277
+ 'estimate_probability_density',
278
+ 'estimate_resolution',
279
+ 'f_test',
280
+ 'fit_ci',
281
+ 'flat_unique',
282
+ 'frames_to_html',
283
+ 'get_default_generators',
284
+ 'get_term_name',
285
+ 'hierarchical',
286
+ 'inclination_displacement',
287
+ 'is_main_parameter',
288
+ 'kolmogorov_smirnov_test',
289
+ 'kurtosis_test',
290
+ 'levene_test',
291
+ 'list_dataset',
292
+ 'load_dataset',
293
+ 'mean_ci',
294
+ 'mean_stability_test',
295
+ 'median_ci',
296
+ 'pairwise_tests',
297
+ 'position_test',
298
+ 'prediction_ci',
299
+ 'proportion_ci',
300
+ 'proportions_test',
301
+ 'root_sum_squares',
302
+ 'round_to_nearest',
303
+ 'sem',
304
+ 'skew_test',
305
+ 'stdev_ci',
306
+ 'style',
307
+ 't_test',
308
+ 'terms_effect',
309
+ 'terms_probability',
310
+ 'uniques',
311
+ 'variance_ci',
312
+ 'variance_inflation_factor',
313
+ 'variance_stability_test',
314
+ 'variance_test',
315
+ ]
@@ -9,6 +9,7 @@ from numpy.typing import NDArray
9
9
  from pandas.core.series import Series
10
10
 
11
11
  __all__ = [
12
+ 'EstimationStrategy',
12
13
  'FloatOrArray',
13
14
  'LegendHandlesLabels',
14
15
  'LineStyle',
@@ -40,6 +41,16 @@ type ShareAxisProperty = (
40
41
  - 'col': share axes within each column
41
42
  """
42
43
 
44
+ type EstimationStrategy = Literal['eval', 'fit', 'norm', 'data']
45
+ """Type alias for estimation strategies for evaluating the probability
46
+ density function (PDF).
47
+
48
+ - 'eval': evaluate the PDF using the given data
49
+ - 'fit': fit a distribution to the data and evaluate the PDF
50
+ - 'norm': assume a normal distribution and evaluate the PDF
51
+ - 'data': use the empirical data to estimate the PDF
52
+ """
53
+
43
54
  type LegendHandlesLabels = (
44
55
  tuple[tuple[Patch |Line2D, ...], tuple[str, ...]])
45
56
  """Type alias as tuple of maptlotlib legend handles and labels."""
@@ -76,7 +76,8 @@ import itertools
76
76
  import warnings
77
77
  from abc import ABC, abstractmethod
78
78
  from collections.abc import Generator
79
- from typing import Any, Literal, LiteralString, Self
79
+ from functools import lru_cache
80
+ from typing import Any, Literal, LiteralString, Self, overload
80
81
 
81
82
  import numpy as np
82
83
  import pandas as pd
@@ -110,19 +111,61 @@ __all__ = [
110
111
  'GageStudyModel',
111
112
  'GeneralizedLinearModel',
112
113
  'LinearModel',
113
- 'get_order',
114
114
  'hierarchical',
115
- 'is_main_parameter',]
115
+ 'interaction_order',
116
+ 'is_main_parameter',
117
+ ]
116
118
 
117
119
 
120
+ @overload
121
+ def _drop_intercept(data: DataFrame) -> DataFrame: ...
122
+ @overload
123
+ def _drop_intercept(data: Series) -> Series: ...
124
+ def _drop_intercept(data: DataFrame | Series) -> DataFrame | Series:
125
+ """Drop the intercept index from a DataFrame or Series if it exists.
126
+
127
+ Parameters
128
+ ----------
129
+ data : DataFrame or Series
130
+ The input data from which to drop the intercept.
131
+
132
+ Returns
133
+ -------
134
+ DataFrame or Series
135
+ The input data with the intercept dropped, if it was present.
136
+ """
137
+ mask = ~data.index.str.contains(ANOVA.INTERCEPT, regex=False)
138
+ if isinstance(data, Series):
139
+ data = data[mask]
140
+ else:
141
+ data = data.loc[mask, :]
142
+ return data.copy()
143
+
118
144
  def is_main_parameter(parameter: str) -> bool:
119
145
  """Check if given parameter is a main parameter (intercept is
120
146
  excluded)."""
121
147
  return parameter != ANOVA.INTERCEPT and ANOVA.SEP not in parameter
122
148
 
123
- def get_order(parameter: str) -> int:
149
+ def interaction_order(parameter: str) -> int:
124
150
  """Get the order of a parameter (i.e., how many interactions it
125
- contains)."""
151
+ contains).
152
+
153
+ Parameters
154
+ ----------
155
+ parameter : str
156
+ The parameter name to check.
157
+
158
+ Returns
159
+ -------
160
+ int
161
+ The interaction order of the parameter.
162
+
163
+ Examples
164
+ --------
165
+ ```python
166
+ interaction_order('x1') # Returns 1
167
+ interaction_order('x1:x2') # Returns 2
168
+ ```"""
126
169
  return parameter.count(ANOVA.SEP) + 1
127
170
 
128
171
  def hierarchical(parameters: list[str]) -> list[str]:
@@ -139,21 +182,28 @@ def hierarchical(parameters: list[str]) -> list[str]:
139
182
  -------
140
183
  h_parameters : list of str
141
184
  Sorted factors for hierarchical model"""
142
-
185
+ return list(_hierarchical_cached(tuple(parameters)))
186
+
187
+ @lru_cache(maxsize=128)
188
+ def _hierarchical_cached(parameters: tuple[str, ...]) -> tuple[str, ...]:
189
+ """Cached implementation of `hierarchical`. Repeated calls with the
190
+ same (unchanged) set of terms, e.g. from `is_hierarchical` during a
191
+ single fit, are then resolved without recomputing all interaction
192
+ subsets."""
143
193
  h_parameters = set(parameters)
144
194
  for parameter in parameters:
145
195
  split = parameter.split(ANOVA.SEP)
146
- n_splits = len(split)
147
- for s in split:
148
- h_parameters.add(s)
149
- if n_splits <= ANOVA.SMALLEST_INTERACTION:
196
+ _order = len(split)
197
+ h_parameters.update(split)
198
+ if _order <= ANOVA.SMALLEST_INTERACTION_ORDER:
150
199
  continue
151
200
 
152
- for i in range(ANOVA.SMALLEST_INTERACTION, n_splits):
153
- for combo in map(ANOVA.SEP.join, itertools.combinations(split, i)):
154
- h_parameters.add(combo)
201
+ h_parameters.update(
202
+ ANOVA.SEP.join(combo)
203
+ for i in range(ANOVA.SMALLEST_INTERACTION_ORDER, _order)
204
+ for combo in itertools.combinations(split, i))
155
205
 
156
- return sorted(sorted(h_parameters), key=get_order)
206
+ return tuple(sorted(h_parameters, key=lambda p: (interaction_order(p), p)))
157
207
 
158
208
 
159
209
  class BaseHTMLReprModel(ABC):
@@ -671,21 +721,55 @@ class LinearModel(BaseHTMLReprModel):
671
721
  """Check if current fitted model is hierarchical."""
672
722
  return all(term in self.terms for term in hierarchical(self.terms))
673
723
 
674
- def effects(self) -> Series:
724
+ def effects(self, include_intercept: bool = True) -> Series:
675
725
  """Calculates the impact of each term on the target. The
676
726
  effects are described as absolute number of the parameter
677
- coefficients devided by its standard error."""
727
+ coefficients devided by its standard error.
728
+
729
+ Parameters
730
+ ----------
731
+ include_intercept : bool, optional
732
+ If False, the intercept is dropped from the returned
733
+ Series, by default True.
734
+
735
+ Returns
736
+ -------
737
+ Series
738
+ A Pandas Series containing the effects of each term on the
739
+ target variable. The index of the Series corresponds to the
740
+ term names, and the values represent the calculated effects.
741
+ """
678
742
  if self._effects.empty:
679
743
  self._effects = terms_effect(self.model)
680
744
  effects = self._effects.copy().rename(index=self.term_map)
745
+ if not include_intercept:
746
+ effects = _drop_intercept(effects)
681
747
  return effects
682
748
 
683
- def p_values(self) -> 'Series[float]':
749
+ def p_values(self, include_intercept: bool = True) -> 'Series[float]':
684
750
  """Get P-value for significance of adding model terms using
685
- anova typ III table for current model."""
751
+ anova typ III table for current model.
752
+
753
+ Parameters
754
+ ----------
755
+ include_intercept : bool, optional
756
+ If False, the intercept is dropped from the returned
757
+ Series, by default True.
758
+
759
+ Returns
760
+ -------
761
+ Series
762
+ A Pandas Series containing the p-values of each term on the
763
+ target variable. The index of the Series corresponds to the
764
+ term names, and the values represent the calculated
765
+ p-values.
766
+ """
686
767
  if self._p_values.empty:
687
768
  self._p_values = terms_probability(self.model)
688
- return self._p_values.copy().rename(index=self.term_map)
769
+ p_values = self._p_values.copy().rename(index=self.term_map)
770
+ if not include_intercept:
771
+ p_values = _drop_intercept(p_values)
772
+ return p_values
689
773
 
690
774
  def least_parameter(self) -> str:
691
775
  """Get the parameter name with the least effect or the least
@@ -706,20 +790,15 @@ class LinearModel(BaseHTMLReprModel):
706
790
  the term name with the least p-value for the F-stats coming from
707
791
  current ANOVA table.
708
792
  """
709
- p_values = self.p_values().copy()
710
- has_intercept = ANOVA.INTERCEPT in p_values.index
793
+ include_intercept = not self.skip_intercept_as_least
794
+ p_values = self.p_values(include_intercept)
711
795
  if any(p_values.isna()):
712
- effects = self.effects().copy()
713
- if has_intercept and self.skip_intercept_as_least:
714
- effects = effects.drop(ANOVA.INTERCEPT)
715
- if any(effects.isna()):
716
- leasts = effects[effects.isna()]
717
- else:
718
- leasts = effects[effects == effects.min()]
719
- least = max(leasts.index, key=get_order)
796
+ effects = self.effects(include_intercept).copy()
797
+ effect_mask = effects.isna()
798
+ if not any(effect_mask):
799
+ effect_mask = effects == effects.min()
800
+ least = max(effects[effect_mask].index, key=interaction_order )
720
801
  else:
721
- if has_intercept and self.skip_intercept_as_least:
722
- p_values = p_values.drop(ANOVA.INTERCEPT)
723
802
  least = p_values.iloc[::-1].idxmax()
724
803
  return str(least)
725
804
 
@@ -945,7 +1024,8 @@ class LinearModel(BaseHTMLReprModel):
945
1024
  get_term_name(self.feature_map.get(x, x))
946
1025
  for x in parameter.split(ANOVA.SEP))
947
1026
  assert term in self.terms, (
948
- f'Given term {term} is not in model')
1027
+ f'Given term {term} (or "{parameter}") is not in model, '
1028
+ f'got: {self.terms}')
949
1029
 
950
1030
  self.excluded.add(term)
951
1031
  return self
@@ -985,7 +1065,7 @@ class LinearModel(BaseHTMLReprModel):
985
1065
  UserWarning)
986
1066
  self.excluded.discard(term)
987
1067
  return self
988
-
1068
+
989
1069
  def recursive_elimination(
990
1070
  self,
991
1071
  rsquared_max: float = 0.99,
@@ -97,9 +97,23 @@ def terms_effect(model: RegressionResultsWrapper) -> Series:
97
97
  Series
98
98
  A pandas Series containing the effects of each factor
99
99
  on the target variable.
100
+
101
+ Notes
102
+ -----
103
+ The effect size is calculated as the absolute value of the parameter
104
+ coefficient divided by its standard error. This is a measure of the
105
+ strength of the relationship between the predictor and the target
106
+ variable, with larger values indicating a stronger effect.
107
+
108
+ The index of the returned Series corresponds to the factor names in
109
+ the model, and the values represent the calculated effect sizes.
110
+
111
+ Only terms that are present in the model are included in the output,
112
+ which is determined by filtering the effects based on the unique
113
+ factor names derived from the model's design information.
100
114
  """
101
115
  params: Series = model.params
102
- se: Series = model.scale
116
+ terms = model.model.data.design_info.term_names
103
117
  names_map = {n: get_term_name(n) for n in params.index}
104
118
  se = (model.bse
105
119
  .rename(index=names_map)
@@ -112,7 +126,7 @@ def terms_effect(model: RegressionResultsWrapper) -> Series:
112
126
  .groupby(level=0)
113
127
  .sum())
114
128
  effects = params.abs() / se
115
- effects = effects[uniques(names_map.values())]
129
+ effects = effects[uniques(n for n in names_map.values() if n in terms)] # Filter out terms that are not in the model (this can happen when the model is imbalanced and some terms are dropped)
116
130
  effects.name = ANOVA.EFFECTS
117
131
  effects.index.name = ANOVA.FACTORS
118
132
  return effects
@@ -549,7 +549,7 @@ class _Anova_:
549
549
  """"Default name for source used in ANOVA table."""
550
550
  VIF: Literal['VIF'] = 'VIF'
551
551
  """"Default column name for VIF values in ANOVA table."""
552
- SMALLEST_INTERACTION: int = 2
552
+ SMALLEST_INTERACTION_ORDER: int = 2
553
553
  """Smallest possible interaction"""
554
554
  RESIDUAL: Literal['Residual'] = 'Residual'
555
555
  """Name in anova table for residual (not explained) values."""
@@ -67,7 +67,12 @@ from numpy.typing import NDArray
67
67
  from pandas.core.frame import DataFrame
68
68
  from pandas.core.series import Series
69
69
 
70
- from .._typing import LegendHandlesLabels, MosaicLayout, ShareAxisProperty
70
+ from .._typing import (
71
+ EstimationStrategy,
72
+ LegendHandlesLabels,
73
+ MosaicLayout,
74
+ ShareAxisProperty,
75
+ )
71
76
  from ..constants import CATEGORY, COLOR, KW, PLOTTER
72
77
  from ..statistics import UNBOUNDED, SpecLimits
73
78
  from ..strings import STR
@@ -1097,7 +1102,7 @@ class SingleChart(Chart):
1097
1102
  control_limits: bool = False,
1098
1103
  spec_limits: SpecLimits = UNBOUNDED,
1099
1104
  confidence: float | None = None,
1100
- strategy: Literal['eval', 'fit', 'norm', 'data'] = 'norm',
1105
+ strategy: EstimationStrategy = 'norm',
1101
1106
  agreement: float | int = 6, # noqa: PYI041
1102
1107
  **kwds,
1103
1108
  ) -> Self:
@@ -1908,7 +1913,7 @@ class JointChart(Chart):
1908
1913
  control_limits: bool | tuple[bool, ...] = False,
1909
1914
  spec_limits: SpecLimits | tuple[SpecLimits, ...] = UNBOUNDED,
1910
1915
  confidence: float | None | tuple[float | None, ...] = None,
1911
- strategy: Literal['eval', 'fit', 'norm', 'data'] | tuple = 'norm',
1916
+ strategy: EstimationStrategy | tuple = 'norm',
1912
1917
  agreement: float | int | tuple[int | float, ...] = 6, # noqa: PYI041
1913
1918
  **kwds) -> Self:
1914
1919
  """Plot location and spread width lines, specification limits
@@ -2369,7 +2374,7 @@ class MultivariateChart(SingleChart):
2369
2374
  control_limits: bool = False,
2370
2375
  spec_limits: SpecLimits = UNBOUNDED,
2371
2376
  confidence: float | None = None,
2372
- strategy: Literal['eval', 'fit', 'norm', 'data'] = 'norm',
2377
+ strategy: EstimationStrategy = 'norm',
2373
2378
  agreement: float | int = 6, # noqa: PYI041
2374
2379
  **kwds,
2375
2380
  ) -> Self:
@@ -61,6 +61,7 @@ from matplotlib.typing import HashableList
61
61
  from numpy.typing import NDArray
62
62
 
63
63
  from .._typing import (
64
+ EstimationStrategy,
64
65
  LegendHandlesLabels,
65
66
  MosaicLayout,
66
67
  NumericSample1D,
@@ -475,7 +476,7 @@ class StripesFacets:
475
476
  control_limits: bool = False,
476
477
  spec_limits: SpecLimits = UNBOUNDED,
477
478
  confidence: float | None = None,
478
- strategy: Literal['eval', 'fit', 'norm', 'data'] = 'norm',
479
+ strategy: EstimationStrategy = 'norm',
479
480
  agreement: float | int = 6, # noqa: PYI041
480
481
  **kwds) -> None:
481
482
  self.single_axes = single_axes