DaSPi 2.4.0__tar.gz → 2.5.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.
- {daspi-2.4.0 → daspi-2.5.0}/PKG-INFO +1 -1
- {daspi-2.4.0 → daspi-2.5.0}/daspi/__init__.py +6 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/anova/model.py +124 -11
- {daspi-2.4.0 → daspi-2.5.0}/daspi/constants.py +39 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/plotlib/chart.py +2 -3
- {daspi-2.4.0 → daspi-2.5.0}/daspi/plotlib/plotter.py +181 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/plotlib/precast.py +309 -30
- {daspi-2.4.0 → daspi-2.5.0}/daspi/strings.py +35 -0
- {daspi-2.4.0 → daspi-2.5.0}/pyproject.toml +1 -1
- {daspi-2.4.0 → daspi-2.5.0}/tests/anova_model_test.py +14 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Formatting_Features_Test_alignments_basic.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Formatting_Features_Test_all_alignments.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Formatting_Features_Test_angles_basic.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Formatting_Features_Test_callable_formatters.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Formatting_Features_Test_combined_all_features.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Formatting_Features_Test_extreme_angles.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Formatting_Features_Test_formatters_basic.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Formatting_Features_Test_formatters_scientific.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Formatting_Features_Test_multivariate_formatting.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Formatting_Features_Test_orientation_mapping.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Formatting_Features_Test_percentage_formatter.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/GaussianKDEContourUnivariate_comparison_with_violin.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/GaussianKDEContourUnivariate_custom_color.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/GaussianKDEContourUnivariate_custom_width.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/GaussianKDEContourUnivariate_joint_chart_mixed_plots.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/GaussianKDEContourUnivariate_multivariate_chart_facets.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/GaussianKDEContourUnivariate_resolution_high.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/GaussianKDEContourUnivariate_single_chart_horizontal.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/GaussianKDEContourUnivariate_single_chart_no_fade.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/GaussianKDEContourUnivariate_single_chart_no_fill.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/GaussianKDEContourUnivariate_single_chart_simple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/GaussianKDEContourUnivariate_single_chart_with_hue.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/JointChart_bar_stacking.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/JointChart_pareto_marked.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/JointChart_probability_dists-prob.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/JointChart_regression_kde.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/MultivariateChart_full-stripes.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/MultivariateChart_full.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Precasts_bivariate-univariate-charts_contour-mean-test.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Precasts_bivariate-univariate-charts_mean-test.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Precasts_bivariate-univariate-charts_simple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Precasts_bivariate-univariate-charts_smoothed.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Precasts_bivariate-univariate-charts_user.png +0 -0
- daspi-2.5.0/tests/charts/Precasts_goodness_of_fit_charts_basic.png +0 -0
- daspi-2.5.0/tests/charts/Precasts_goodness_of_fit_charts_refit-epoch-7.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Precasts_pair_comparison_charts_basic.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Precasts_parameter_relevance_charts_basic.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Precasts_process-capabity-analysis-charts_hue.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Precasts_residual_charts_basic.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_KDE-cumulative_multiple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_KDE_multiple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_KDE_ridge.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_beeswarm_multiple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_beeswarm_simple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_blandaltman_simple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_blandaltman_user.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_box_fill.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_box_multiple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_box_simple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_categorical-float-features_simple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_errorbar_mean-test.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_errorbar_sem.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_errorbar_std-test.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_errorbar_var-test.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_fitted-density_cdf-multiple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_jitter_multiple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_jitter_simple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_line_hue.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_line_hue_size.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_pareto-threshold_simple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_pareto_simple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_pareto_transposed.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_quantiles_multiple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_quantiles_simple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_scatter_full.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_scatter_hue-shape.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_scatter_hue-size.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_scatter_hue.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_scatter_shape.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_scatter_size-shape.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_scatter_size.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_violin_mono.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_violin_multiple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_violin_simple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/plotlib_plotter_test.py +150 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/plotlib_visual_test.py +53 -0
- {daspi-2.4.0 → daspi-2.5.0}/LICENSE +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/README.md +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/_typing.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/_version.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/anova/__init__.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/anova/convert.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/anova/tables.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/config.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/__init__.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/ancova.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/anova.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/anova2.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/anova2_unbalanced.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/anova3.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/anova3_unbalanced.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/carpet_full-factorial.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/covariate.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/drop_card.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/eeprom_full-factorial.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/eeprom_partial-factorial.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/grnr_adjustment.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/grnr_layer_thickness.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/grnr_spc.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/iris.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/mpg.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/painkillers-dissolution.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/partial_factorial.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/penguins.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/process_capability.mpx +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/salt_sticks.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/shoe-sole.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/datasets/tips.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/doe/__init__.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/doe/build.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/plotlib/__init__.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/plotlib/appearance.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/plotlib/classify.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/plotlib/facets.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/plotlib/styles/daspi-dark.mplstyle +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/plotlib/styles/daspi.mplstyle +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/plotlib/styles/ggplot2.mplstyle +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/plotlib/styles/seaborn.mplstyle +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/requirements.txt +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/statistics/__init__.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/statistics/confidence.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/statistics/estimation.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/statistics/hypothesis.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/daspi/statistics/montecarlo.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/ANOVA_SS_Fehler.mpx +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/ANOVA_SS_Fehler.mpx.bak +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/GageRnR.mpx +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/GageRnR.mpx.bak +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/__init__.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/anova_convert_test.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/anova_tables_test.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/JointChart_kdes_kde-mean.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/JointChart_kdes_mixed-kde.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/JointChart_probability_norm-prob.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Precasts_gage_rnr_model_basic.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/Precasts_gage_study_model_basic.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_KDE-cumulative_simple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_KDE_simple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_fitted-density_pdf-data.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_fitted-density_pdf-norm.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_scatter_simple-stripes-65ci.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_scatter_simple-stripes-99ci.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_scatter_simple-stripes.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_scatter_simple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_scatter_transposed.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_violine-contour_simple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_violine_mono.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_violine_multiple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/SingleChart_violine_simple.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/_debug_kde_bottom_crop.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/_debug_violin_bottom_crop.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/charts/_debug_violin_top_crop.png +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/config_test.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/data/anova3_result.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/data/dists_10-samples.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/data/dists_25-samples.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/data/gage_rnr.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/data/gage_study.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/data/generate_dists.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/data/grnr_d-optimal.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/data/uncertainties.csv +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/doe_build_test.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/plotlib_appearance_test.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/plotlib_chart_test.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/plotlib_classify_test.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/plotlib_facets_test.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/plotlib_templates_test.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/r2_pred.mpx +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/r2_pred.mpx.bak +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/statistics_confidence_test.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/statistics_estimation_test.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/statistics_hypothesis_test.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/statistics_montecarlo_test.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/strings_test.py +0 -0
- {daspi-2.4.0 → daspi-2.5.0}/tests/test_full_factorial_design_builder.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: DaSPi
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.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
5
|
Author-Email: Reto Jäggli <reto@jaeggli.email>
|
|
6
6
|
License: MIT
|
|
@@ -101,6 +101,7 @@ if TYPE_CHECKING:
|
|
|
101
101
|
SpreadWidth,
|
|
102
102
|
StandardErrorMean,
|
|
103
103
|
Stem,
|
|
104
|
+
StripeArea,
|
|
104
105
|
StripeLine,
|
|
105
106
|
StripeSpan,
|
|
106
107
|
TransformPlotter,
|
|
@@ -111,6 +112,7 @@ if TYPE_CHECKING:
|
|
|
111
112
|
BivariateUnivariateCharts,
|
|
112
113
|
GageRnRCharts,
|
|
113
114
|
GageStudyCharts,
|
|
115
|
+
GoodnessOfFitCharts,
|
|
114
116
|
PairComparisonCharts,
|
|
115
117
|
PairwiseMatrixCharts,
|
|
116
118
|
ParameterRelevanceCharts,
|
|
@@ -259,6 +261,7 @@ _LAZY_SUBMODULES: dict[str, str] = {
|
|
|
259
261
|
'SpreadWidth': '.plotlib.plotter',
|
|
260
262
|
'StandardErrorMean': '.plotlib.plotter',
|
|
261
263
|
'Stem': '.plotlib.plotter',
|
|
264
|
+
'StripeArea': '.plotlib.plotter',
|
|
262
265
|
'StripeLine': '.plotlib.plotter',
|
|
263
266
|
'StripeSpan': '.plotlib.plotter',
|
|
264
267
|
'TransformPlotter': '.plotlib.plotter',
|
|
@@ -267,6 +270,7 @@ _LAZY_SUBMODULES: dict[str, str] = {
|
|
|
267
270
|
'BivariateUnivariateCharts': '.plotlib.precast',
|
|
268
271
|
'GageRnRCharts': '.plotlib.precast',
|
|
269
272
|
'GageStudyCharts': '.plotlib.precast',
|
|
273
|
+
'GoodnessOfFitCharts': '.plotlib.precast',
|
|
270
274
|
'PairComparisonCharts': '.plotlib.precast',
|
|
271
275
|
'PairwiseMatrixCharts': '.plotlib.precast',
|
|
272
276
|
'ParameterRelevanceCharts': '.plotlib.precast',
|
|
@@ -401,6 +405,7 @@ __all__ = [
|
|
|
401
405
|
'MeanTest',
|
|
402
406
|
'MeasurementUncertainty',
|
|
403
407
|
'MultivariateChart',
|
|
408
|
+
'GoodnessOfFitCharts',
|
|
404
409
|
'PairComparisonCharts',
|
|
405
410
|
'PairwiseMatrixCharts',
|
|
406
411
|
'ParallelCoordinate',
|
|
@@ -424,6 +429,7 @@ __all__ = [
|
|
|
424
429
|
'SpreadWidth',
|
|
425
430
|
'StandardErrorMean',
|
|
426
431
|
'Stem',
|
|
432
|
+
'StripeArea',
|
|
427
433
|
'StripeLine',
|
|
428
434
|
'StripeSpan',
|
|
429
435
|
'StripesFacets',
|
|
@@ -374,8 +374,7 @@ class LinearModel(BaseHTMLReprModel):
|
|
|
374
374
|
target='dissolution',
|
|
375
375
|
factors=['employee', 'stirrer', 'brand', 'catalyst', 'water'],
|
|
376
376
|
covariates=['temperature', 'preparation'],
|
|
377
|
-
order=2,
|
|
378
|
-
covariates=None)
|
|
377
|
+
order=2,)
|
|
379
378
|
|
|
380
379
|
# Store goodnes of fit values for each elimination step
|
|
381
380
|
df_gof = pd.concat(model.recursive_elimination())
|
|
@@ -883,7 +882,11 @@ class LinearModel(BaseHTMLReprModel):
|
|
|
883
882
|
DataFrame
|
|
884
883
|
The goodness-of-fit metrics table as DataFrame containing
|
|
885
884
|
the following columns:
|
|
886
|
-
- '
|
|
885
|
+
- 'epoch' = the given `index`, i.e. the step at which a term
|
|
886
|
+
was added or removed during recursive elimination
|
|
887
|
+
- 'formula' = current formula, can be used to refit the
|
|
888
|
+
model at this step, see `formula_at_epoch` and
|
|
889
|
+
`refit_at_epoch`
|
|
887
890
|
- 's' = Uncertainty of the model as square root of MS_Residual
|
|
888
891
|
- 'aic' = Akaike's information criteria
|
|
889
892
|
- 'r2' = R-squared of the model
|
|
@@ -895,17 +898,127 @@ class LinearModel(BaseHTMLReprModel):
|
|
|
895
898
|
"""
|
|
896
899
|
self.anova(typ='III', vif=False)
|
|
897
900
|
data = {
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
901
|
+
ANOVA.EPOCH: index + 1 if isinstance(index, int) else index,
|
|
902
|
+
ANOVA.FORMULA: self.formula,
|
|
903
|
+
ANOVA.HIERARCHICAL: self.is_hierarchical(),
|
|
904
|
+
ANOVA.LEAST_PARAMETER: self.least_parameter(),
|
|
905
|
+
ANOVA.P_LEAST: self.p_values().max(),
|
|
902
906
|
's': self.uncertainty,
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
+
ANOVA.AIC: self.model.aic,
|
|
908
|
+
ANOVA.R2: self.model.rsquared,
|
|
909
|
+
ANOVA.R2_ADJ: self.model.rsquared_adj,
|
|
910
|
+
ANOVA.R2_PRED: self.r2_pred()}
|
|
907
911
|
return pd.DataFrame(data, index=[index])
|
|
908
912
|
|
|
913
|
+
@staticmethod
|
|
914
|
+
def formula_at_epoch(df_gof: DataFrame, epoch: int) -> str:
|
|
915
|
+
"""Extract the model formula recorded at a given elimination
|
|
916
|
+
step from a goodness-of-fit table.
|
|
917
|
+
|
|
918
|
+
Parameters
|
|
919
|
+
----------
|
|
920
|
+
df_gof : DataFrame
|
|
921
|
+
The goodness-of-fit table collected during recursive
|
|
922
|
+
elimination, i.e. the concatenated result of
|
|
923
|
+
`recursive_elimination`. Must contain the columns 'epoch'
|
|
924
|
+
and 'formula', see `gof_metrics`.
|
|
925
|
+
epoch : int
|
|
926
|
+
The elimination step whose formula should be extracted.
|
|
927
|
+
|
|
928
|
+
Returns
|
|
929
|
+
-------
|
|
930
|
+
str
|
|
931
|
+
The model formula used at the given `epoch`.
|
|
932
|
+
|
|
933
|
+
Examples
|
|
934
|
+
--------
|
|
935
|
+
```python
|
|
936
|
+
import pandas as pd
|
|
937
|
+
import daspi as dsp
|
|
938
|
+
|
|
939
|
+
df = dsp.load_dataset('painkillers-dissolution')
|
|
940
|
+
lm = dsp.LinearModel(
|
|
941
|
+
source=df,
|
|
942
|
+
target='dissolution',
|
|
943
|
+
factors=['employee', 'stirrer', 'brand', 'catalyst', 'water'],
|
|
944
|
+
covariates=['temperature', 'preparation'],
|
|
945
|
+
order=2)
|
|
946
|
+
df_gof = pd.concat(lm.recursive_elimination())
|
|
947
|
+
dsp.LinearModel.formula_at_epoch(df_gof, epoch=5)
|
|
948
|
+
```
|
|
949
|
+
"""
|
|
950
|
+
rows = df_gof[df_gof[ANOVA.EPOCH] == epoch]
|
|
951
|
+
assert not rows.empty, (
|
|
952
|
+
f'No entry found for epoch={epoch} in df_gof, got epochs '
|
|
953
|
+
f'{sorted(df_gof[ANOVA.EPOCH].unique())}')
|
|
954
|
+
return str(rows[ANOVA.FORMULA].iloc[0])
|
|
955
|
+
|
|
956
|
+
def refit_at_epoch(self, df_gof: DataFrame, epoch: int, **kwds) -> Self:
|
|
957
|
+
"""Refit this model using the formula recorded at a given
|
|
958
|
+
elimination step of a goodness-of-fit table.
|
|
959
|
+
|
|
960
|
+
This is a convenience method combining `formula_at_epoch` and
|
|
961
|
+
`fit`, allowing you to go back to any intermediate step of a
|
|
962
|
+
previously run `recursive_elimination` once you have picked a
|
|
963
|
+
preferred epoch, e.g. by inspecting a
|
|
964
|
+
`daspi.GoodnessOfFitCharts` plot.
|
|
965
|
+
|
|
966
|
+
Parameters
|
|
967
|
+
----------
|
|
968
|
+
df_gof : DataFrame
|
|
969
|
+
The goodness-of-fit table collected during recursive
|
|
970
|
+
elimination, i.e. the concatenated result of
|
|
971
|
+
`recursive_elimination`. Must contain the columns 'epoch'
|
|
972
|
+
and 'formula', see `gof_metrics`.
|
|
973
|
+
epoch : int
|
|
974
|
+
The elimination step whose formula should be used to refit
|
|
975
|
+
the model.
|
|
976
|
+
**kwds
|
|
977
|
+
Additional keyword arguments for `ols` function of
|
|
978
|
+
`statsmodels.formula.api`, passed to `fit`.
|
|
979
|
+
|
|
980
|
+
Returns
|
|
981
|
+
-------
|
|
982
|
+
Self
|
|
983
|
+
The current instance of the model, refitted with the
|
|
984
|
+
formula of the given `epoch`, for method chaining.
|
|
985
|
+
|
|
986
|
+
Notes
|
|
987
|
+
-----
|
|
988
|
+
This also resyncs the `excluded` attribute so that the
|
|
989
|
+
`formula` property and methods relying on it (`eliminate`,
|
|
990
|
+
`include`, `recursive_elimination`) stay consistent with the
|
|
991
|
+
formula used for refitting.
|
|
992
|
+
|
|
993
|
+
Examples
|
|
994
|
+
--------
|
|
995
|
+
```python
|
|
996
|
+
import pandas as pd
|
|
997
|
+
import daspi as dsp
|
|
998
|
+
|
|
999
|
+
df = dsp.load_dataset('painkillers-dissolution')
|
|
1000
|
+
lm = dsp.LinearModel(
|
|
1001
|
+
source=df,
|
|
1002
|
+
target='dissolution',
|
|
1003
|
+
factors=['employee', 'stirrer', 'brand', 'catalyst', 'water'],
|
|
1004
|
+
covariates=['temperature', 'preparation'],
|
|
1005
|
+
order=2)
|
|
1006
|
+
df_gof = pd.concat(lm.recursive_elimination())
|
|
1007
|
+
lm.refit_at_epoch(df_gof, epoch=5)
|
|
1008
|
+
dsp.ParameterRelevanceCharts(lm).plot().stripes().label()
|
|
1009
|
+
```
|
|
1010
|
+
"""
|
|
1011
|
+
formula = self.formula_at_epoch(df_gof, epoch)
|
|
1012
|
+
terms = [t.strip() for t in formula.split('~', 1)[1].split('+')]
|
|
1013
|
+
drop_intercept = '-1' in terms
|
|
1014
|
+
terms = [t for t in terms if t != '-1']
|
|
1015
|
+
self.excluded = {t for t in self._initial_terms if t not in terms}
|
|
1016
|
+
if drop_intercept:
|
|
1017
|
+
self.excluded.add(ANOVA.INTERCEPT)
|
|
1018
|
+
else:
|
|
1019
|
+
self.excluded.discard(ANOVA.INTERCEPT)
|
|
1020
|
+
return self.fit(**kwds)
|
|
1021
|
+
|
|
909
1022
|
def summary(
|
|
910
1023
|
self,
|
|
911
1024
|
anova_typ: Literal['', 'I', 'II', 'III'] | None = None,
|
|
@@ -843,6 +843,45 @@ class _Anova_:
|
|
|
843
843
|
"""Default column name for the Variance Inflation Factor values used
|
|
844
844
|
to detect multicollinearity in an ANOVA table."""
|
|
845
845
|
|
|
846
|
+
EPOCH: Literal['epoch'] = 'epoch'
|
|
847
|
+
"""Column name for the step at which a term was added or removed
|
|
848
|
+
during recursive elimination in a goodness-of-fit table, see
|
|
849
|
+
`LinearModel.gof_metrics`."""
|
|
850
|
+
|
|
851
|
+
FORMULA: Literal['formula'] = 'formula'
|
|
852
|
+
"""Column name for the model formula at a given elimination step in
|
|
853
|
+
a goodness-of-fit table, see `LinearModel.gof_metrics` and
|
|
854
|
+
`LinearModel.formula_at_epoch`."""
|
|
855
|
+
|
|
856
|
+
HIERARCHICAL: Literal['hierarchical'] = 'hierarchical'
|
|
857
|
+
"""Column name for the flag indicating whether the model is
|
|
858
|
+
hierarchical in a goodness-of-fit table, see
|
|
859
|
+
`LinearModel.gof_metrics`."""
|
|
860
|
+
|
|
861
|
+
LEAST_PARAMETER: Literal['least_parameter'] = 'least_parameter'
|
|
862
|
+
"""Column name for the least significant term in a goodness-of-fit
|
|
863
|
+
table, see `LinearModel.gof_metrics`."""
|
|
864
|
+
|
|
865
|
+
P_LEAST: Literal['p_least'] = 'p_least'
|
|
866
|
+
"""Column name for the p-value of the least significant term in a
|
|
867
|
+
goodness-of-fit table, see `LinearModel.gof_metrics`."""
|
|
868
|
+
|
|
869
|
+
AIC: Literal['aic'] = 'aic'
|
|
870
|
+
"""Column name for Akaike's information criterion in a
|
|
871
|
+
goodness-of-fit table, see `LinearModel.gof_metrics`."""
|
|
872
|
+
|
|
873
|
+
R2: Literal['r2'] = 'r2'
|
|
874
|
+
"""Column name for R-squared in a goodness-of-fit table, see
|
|
875
|
+
`LinearModel.gof_metrics`."""
|
|
876
|
+
|
|
877
|
+
R2_ADJ: Literal['r2_adj'] = 'r2_adj'
|
|
878
|
+
"""Column name for adjusted R-squared in a goodness-of-fit table,
|
|
879
|
+
see `LinearModel.gof_metrics`."""
|
|
880
|
+
|
|
881
|
+
R2_PRED: Literal['r2_pred'] = 'r2_pred'
|
|
882
|
+
"""Column name for predicted R-squared in a goodness-of-fit table,
|
|
883
|
+
see `LinearModel.gof_metrics`."""
|
|
884
|
+
|
|
846
885
|
SMALLEST_INTERACTION_ORDER: int = 2
|
|
847
886
|
"""Smallest possible interaction order, i.e. the interaction between
|
|
848
887
|
two factors (A:B)."""
|
|
@@ -934,9 +934,8 @@ class SingleChart(Chart):
|
|
|
934
934
|
if not isinstance(combination, tuple):
|
|
935
935
|
combination = (combination, )
|
|
936
936
|
self._last_variate = deepcopy(self._current_variate)
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
937
|
+
self._current_variate |= dict(zip(self.variate_names, combination))
|
|
938
|
+
|
|
940
939
|
def dodge(self) -> None:
|
|
941
940
|
"""Converts the feature data to tick positions, taking dodging
|
|
942
941
|
into account."""
|
|
@@ -169,6 +169,7 @@ __all__ = [
|
|
|
169
169
|
'StandardErrorMean',
|
|
170
170
|
'Stem',
|
|
171
171
|
'Stripe',
|
|
172
|
+
'StripeArea',
|
|
172
173
|
'StripeLine',
|
|
173
174
|
'StripeSpan',
|
|
174
175
|
'TransformPlotter',
|
|
@@ -8314,6 +8315,186 @@ class StripeSpan(Stripe):
|
|
|
8314
8315
|
self._axes.append(ax)
|
|
8315
8316
|
|
|
8316
8317
|
|
|
8318
|
+
class StripeArea(Stripe):
|
|
8319
|
+
"""Concrete implementation of `Stripe` for filling the area between
|
|
8320
|
+
two boundary curves using `fill_between`/`fill_betweenx`.
|
|
8321
|
+
|
|
8322
|
+
Unlike `StripeSpan`, which draws a constant band across the full
|
|
8323
|
+
plotting area with `axhspan`/`axvspan`, `StripeArea` fills the
|
|
8324
|
+
region between two boundary curves that may vary along the
|
|
8325
|
+
orthogonal axis (e.g. a confidence band around a fitted line, or
|
|
8326
|
+
spec limits that change over the feature range). The `where`
|
|
8327
|
+
parameter allows the fill to be restricted to specific sections of
|
|
8328
|
+
the data range, exactly like the `where` argument of Matplotlib's
|
|
8329
|
+
`fill_between`/`fill_betweenx`.
|
|
8330
|
+
|
|
8331
|
+
Parameters
|
|
8332
|
+
----------
|
|
8333
|
+
label : str
|
|
8334
|
+
The label of the stripe as it appears in the legend.
|
|
8335
|
+
base : array-like
|
|
8336
|
+
The data coordinates along the orthogonal axis (x for
|
|
8337
|
+
horizontal stripes, y for vertical stripes) that the lower and
|
|
8338
|
+
upper boundary values correspond to.
|
|
8339
|
+
lower_values : array-like or float
|
|
8340
|
+
The lower boundary of the filled area for each `base` value.
|
|
8341
|
+
Scalars are broadcast across `base`.
|
|
8342
|
+
upper_values : array-like or float
|
|
8343
|
+
The upper boundary of the filled area for each `base` value.
|
|
8344
|
+
Scalars are broadcast across `base`.
|
|
8345
|
+
where : array-like of bool or None, optional
|
|
8346
|
+
Boolean mask defining where the area should be filled, passed
|
|
8347
|
+
directly to `fill_between`/`fill_betweenx`. If None, the area is
|
|
8348
|
+
filled across the entire `base` range. Defaults to None.
|
|
8349
|
+
interpolate : bool, optional
|
|
8350
|
+
Whether to interpolate the boundaries at the edges of masked
|
|
8351
|
+
regions defined by `where`, passed to
|
|
8352
|
+
`fill_between`/`fill_betweenx`. Defaults to False.
|
|
8353
|
+
step : {'pre', 'post', 'mid'} or None, optional
|
|
8354
|
+
If not None, fill between `base` and the boundaries using steps
|
|
8355
|
+
of the given style, passed to `fill_between`/`fill_betweenx`.
|
|
8356
|
+
Defaults to None.
|
|
8357
|
+
orientation : {'horizontal', 'vertical'}, optional
|
|
8358
|
+
The orientation of the stripe. Defaults to 'horizontal'.
|
|
8359
|
+
color : str, optional
|
|
8360
|
+
The fill color of the stripe. Defaults to `COLOR.STRIPE`.
|
|
8361
|
+
alpha : float, optional
|
|
8362
|
+
Transparency level of the stripe. Defaults to `COLOR.CI_ALPHA`.
|
|
8363
|
+
zorder : float, optional
|
|
8364
|
+
Drawing order of the stripe. Defaults to 0.7.
|
|
8365
|
+
border_linewidth : float, optional
|
|
8366
|
+
Width of the border line. Can also be set via `lw` or
|
|
8367
|
+
`linewidth` in `**kwds`. Defaults to 0.
|
|
8368
|
+
**kwds :
|
|
8369
|
+
Additional keyword arguments for fine-tuning appearance.
|
|
8370
|
+
Priority order:
|
|
8371
|
+
- Line width: `lw`, `linewidth`, then `border_linewidth`
|
|
8372
|
+
- Color: `c`, then `color`
|
|
8373
|
+
|
|
8374
|
+
Examples
|
|
8375
|
+
--------
|
|
8376
|
+
Apply to an existing Axes object:
|
|
8377
|
+
|
|
8378
|
+
```python
|
|
8379
|
+
import numpy as np
|
|
8380
|
+
import matplotlib.pyplot as plt
|
|
8381
|
+
from daspi import StripeArea, COLOR
|
|
8382
|
+
|
|
8383
|
+
fig, ax = plt.subplots()
|
|
8384
|
+
x = np.linspace(0, 10, 100)
|
|
8385
|
+
lower = np.sin(x) - 0.3
|
|
8386
|
+
upper = np.sin(x) + 0.3
|
|
8387
|
+
band = StripeArea(
|
|
8388
|
+
label='band',
|
|
8389
|
+
base=x,
|
|
8390
|
+
lower_values=lower,
|
|
8391
|
+
upper_values=upper,
|
|
8392
|
+
where=x > 5,
|
|
8393
|
+
color=COLOR.STRIPE)
|
|
8394
|
+
band(ax=ax)
|
|
8395
|
+
ax.legend([band.handle], [band.label])
|
|
8396
|
+
```
|
|
8397
|
+
|
|
8398
|
+
Notes
|
|
8399
|
+
-----
|
|
8400
|
+
This class is part of the DaSPi visualization toolkit and is
|
|
8401
|
+
designed to integrate seamlessly with other chart components. It
|
|
8402
|
+
ensures that each stripe is only drawn once per Axes instance.
|
|
8403
|
+
"""
|
|
8404
|
+
|
|
8405
|
+
__slots__ = (
|
|
8406
|
+
'base',
|
|
8407
|
+
'border_linewidth',
|
|
8408
|
+
'interpolate',
|
|
8409
|
+
'lower_values',
|
|
8410
|
+
'step',
|
|
8411
|
+
'upper_values',
|
|
8412
|
+
'where')
|
|
8413
|
+
|
|
8414
|
+
base: NDArray
|
|
8415
|
+
"""The data coordinates along the orthogonal axis the boundary
|
|
8416
|
+
values correspond to."""
|
|
8417
|
+
border_linewidth: float
|
|
8418
|
+
"""Width of the border line. Could also be set during initialisation
|
|
8419
|
+
via `lw` or `linewidth`."""
|
|
8420
|
+
interpolate: bool
|
|
8421
|
+
"""Whether to interpolate the boundaries at the edges of masked
|
|
8422
|
+
regions defined by `where`."""
|
|
8423
|
+
lower_values: NDArray
|
|
8424
|
+
"""The lower boundary of the filled area for each `base` value."""
|
|
8425
|
+
step: Literal['pre', 'post', 'mid'] | None
|
|
8426
|
+
"""If not None, fill using steps of the given style."""
|
|
8427
|
+
upper_values: NDArray
|
|
8428
|
+
"""The upper boundary of the filled area for each `base` value."""
|
|
8429
|
+
where: NDArray | None
|
|
8430
|
+
"""Boolean mask defining where the area should be filled."""
|
|
8431
|
+
|
|
8432
|
+
def __init__(
|
|
8433
|
+
self,
|
|
8434
|
+
label: str,
|
|
8435
|
+
base: ArrayLike,
|
|
8436
|
+
lower_values: ArrayLike | float,
|
|
8437
|
+
upper_values: ArrayLike | float,
|
|
8438
|
+
where: ArrayLike | None = None,
|
|
8439
|
+
interpolate: bool = False,
|
|
8440
|
+
step: Literal['pre', 'post', 'mid'] | None = None,
|
|
8441
|
+
orientation: Literal['horizontal', 'vertical'] = 'horizontal',
|
|
8442
|
+
color: str = COLOR.STRIPE,
|
|
8443
|
+
alpha: float = COLOR.CI_ALPHA,
|
|
8444
|
+
zorder: float = 0.7,
|
|
8445
|
+
border_linewidth: float = 0,
|
|
8446
|
+
**kwds) -> None:
|
|
8447
|
+
self.base = np.asarray(base, dtype=float)
|
|
8448
|
+
self.lower_values = np.broadcast_to(
|
|
8449
|
+
np.asarray(lower_values, dtype=float), self.base.shape)
|
|
8450
|
+
self.upper_values = np.broadcast_to(
|
|
8451
|
+
np.asarray(upper_values, dtype=float), self.base.shape)
|
|
8452
|
+
self.where = None if where is None else np.asarray(where, dtype=bool)
|
|
8453
|
+
self.interpolate = interpolate
|
|
8454
|
+
self.step = step
|
|
8455
|
+
|
|
8456
|
+
position = float(np.mean(self.lower_values + self.upper_values) / 2)
|
|
8457
|
+
width = float(np.mean(self.upper_values - self.lower_values))
|
|
8458
|
+
super().__init__(
|
|
8459
|
+
label=label,
|
|
8460
|
+
orientation=orientation,
|
|
8461
|
+
position=position,
|
|
8462
|
+
width=width,
|
|
8463
|
+
color=kwds.get('c', color),
|
|
8464
|
+
alpha=alpha,
|
|
8465
|
+
zorder=zorder,
|
|
8466
|
+
show_position=False)
|
|
8467
|
+
self.border_linewidth = kwds.get(
|
|
8468
|
+
'lw', kwds.get('linewidth', border_linewidth))
|
|
8469
|
+
|
|
8470
|
+
@property
|
|
8471
|
+
def handle(self) -> Patch:
|
|
8472
|
+
"""Get the handle of the stripe used for legend."""
|
|
8473
|
+
handle = Patch(color=self.color, alpha=self.alpha)
|
|
8474
|
+
return handle
|
|
8475
|
+
|
|
8476
|
+
def __call__(self, ax: Axes) -> None:
|
|
8477
|
+
"""Draw the stripe on the given Axes object."""
|
|
8478
|
+
if ax in self._axes:
|
|
8479
|
+
return
|
|
8480
|
+
|
|
8481
|
+
kwds = {
|
|
8482
|
+
'color': self.color,
|
|
8483
|
+
'alpha': self.alpha,
|
|
8484
|
+
'linewidth': self.border_linewidth,
|
|
8485
|
+
'zorder': self.zorder,
|
|
8486
|
+
'where': self.where,
|
|
8487
|
+
'interpolate': self.interpolate,
|
|
8488
|
+
'step': self.step}
|
|
8489
|
+
if self.orientation == 'horizontal':
|
|
8490
|
+
ax.fill_between(
|
|
8491
|
+
self.base, self.lower_values, self.upper_values, **kwds)
|
|
8492
|
+
else:
|
|
8493
|
+
ax.fill_betweenx(
|
|
8494
|
+
self.base, self.lower_values, self.upper_values, **kwds)
|
|
8495
|
+
self._axes.append(ax)
|
|
8496
|
+
|
|
8497
|
+
|
|
8317
8498
|
class BlandAltman(Plotter):
|
|
8318
8499
|
"""Generate a Bland-Altman plot to compare two sets of measurements.
|
|
8319
8500
|
|