numdaplot 0.1.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.
- numdaplot/__init__.py +506 -0
- numdaplot/arrays/__init__.py +5 -0
- numdaplot/arrays/array.py +92 -0
- numdaplot/arrays/array_arithmetic.py +404 -0
- numdaplot/arrays/array_calculation.py +143 -0
- numdaplot/arrays/array_conversion.py +150 -0
- numdaplot/arrays/array_creation.py +371 -0
- numdaplot/arrays/array_data.py +281 -0
- numdaplot/arrays/array_layout.py +179 -0
- numdaplot/arrays/array_logic.py +227 -0
- numdaplot/arrays/array_reflected_arithmetic.py +334 -0
- numdaplot/arrays/array_refusals.py +339 -0
- numdaplot/arrays/array_selection.py +195 -0
- numdaplot/arrays/array_sorting.py +59 -0
- numdaplot/arrays/axis_number.py +58 -0
- numdaplot/arrays/calculation/__init__.py +5 -0
- numdaplot/arrays/calculation/counting_statistics.py +325 -0
- numdaplot/arrays/calculation/location_statistics.py +268 -0
- numdaplot/arrays/calculation/math_function_values.py +183 -0
- numdaplot/arrays/calculation/statistic_values.py +209 -0
- numdaplot/arrays/calculation/time_function_values.py +419 -0
- numdaplot/arrays/conversion/__init__.py +5 -0
- numdaplot/arrays/conversion/array_text.py +62 -0
- numdaplot/arrays/conversion/equality_check.py +72 -0
- numdaplot/arrays/conversion/python_values.py +70 -0
- numdaplot/arrays/conversion/time_text.py +290 -0
- numdaplot/arrays/creation/__init__.py +5 -0
- numdaplot/arrays/creation/date_parts.py +89 -0
- numdaplot/arrays/creation/date_parts_values.py +437 -0
- numdaplot/arrays/creation/distribution.py +54 -0
- numdaplot/arrays/creation/filled_values.py +58 -0
- numdaplot/arrays/creation/list_conversion.py +311 -0
- numdaplot/arrays/creation/list_shape.py +97 -0
- numdaplot/arrays/creation/normal.py +65 -0
- numdaplot/arrays/creation/numpy_conversion.py +149 -0
- numdaplot/arrays/creation/random_integers.py +104 -0
- numdaplot/arrays/creation/random_values.py +97 -0
- numdaplot/arrays/creation/range_values.py +73 -0
- numdaplot/arrays/creation/spacing.py +84 -0
- numdaplot/arrays/creation/spacing_values.py +63 -0
- numdaplot/arrays/creation/uniform.py +63 -0
- numdaplot/arrays/equality.py +68 -0
- numdaplot/arrays/layout/__init__.py +5 -0
- numdaplot/arrays/layout/sorting_values.py +113 -0
- numdaplot/arrays/layout/unique_values.py +49 -0
- numdaplot/arrays/mapping/__init__.py +5 -0
- numdaplot/arrays/mapping/mapped_values.py +286 -0
- numdaplot/arrays/mapping/unmatched.py +50 -0
- numdaplot/arrays/mapping/value_change.py +55 -0
- numdaplot/arrays/mapping/value_mapping.py +161 -0
- numdaplot/arrays/math_functions/__init__.py +5 -0
- numdaplot/arrays/math_functions/absolute.py +27 -0
- numdaplot/arrays/math_functions/cosine.py +28 -0
- numdaplot/arrays/math_functions/exponential.py +27 -0
- numdaplot/arrays/math_functions/logarithm.py +72 -0
- numdaplot/arrays/math_functions/math_function.py +58 -0
- numdaplot/arrays/math_functions/round.py +58 -0
- numdaplot/arrays/math_functions/sine.py +28 -0
- numdaplot/arrays/math_functions/square_root.py +27 -0
- numdaplot/arrays/operations/__init__.py +5 -0
- numdaplot/arrays/operations/boolean_operands.py +48 -0
- numdaplot/arrays/operations/combination.py +157 -0
- numdaplot/arrays/operations/float_errors.py +170 -0
- numdaplot/arrays/operations/integer_bounds.py +175 -0
- numdaplot/arrays/operations/integer_rules.py +397 -0
- numdaplot/arrays/operations/operand.py +139 -0
- numdaplot/arrays/operations/time_arithmetic.py +479 -0
- numdaplot/arrays/operations/time_bounds.py +286 -0
- numdaplot/arrays/operations/time_result_bounds.py +397 -0
- numdaplot/arrays/operations/transformation.py +54 -0
- numdaplot/arrays/operations/type_requirements.py +94 -0
- numdaplot/arrays/replacement.py +66 -0
- numdaplot/arrays/selection/__init__.py +5 -0
- numdaplot/arrays/selection/comparison_masks.py +131 -0
- numdaplot/arrays/selection/membership_masks.py +118 -0
- numdaplot/arrays/selection/missing_mask.py +50 -0
- numdaplot/arrays/selection/region_index.py +178 -0
- numdaplot/arrays/selection/replaced_values.py +120 -0
- numdaplot/arrays/selection/rule_mask.py +83 -0
- numdaplot/arrays/selection/time_reference.py +172 -0
- numdaplot/arrays/shape.py +74 -0
- numdaplot/arrays/type_match.py +51 -0
- numdaplot/data_types/__init__.py +5 -0
- numdaplot/data_types/library.py +57 -0
- numdaplot/data_types/numpy_mapping.py +207 -0
- numdaplot/data_types/pandas_mapping.py +114 -0
- numdaplot/data_types/time_of_day.py +292 -0
- numdaplot/data_types/type.py +224 -0
- numdaplot/data_types/value_family.py +149 -0
- numdaplot/data_types/value_type.py +147 -0
- numdaplot/dates/__init__.py +5 -0
- numdaplot/dates/custom_date_format.py +83 -0
- numdaplot/dates/date_format.py +120 -0
- numdaplot/dates/date_part.py +59 -0
- numdaplot/dates/date_part_unit.py +153 -0
- numdaplot/dates/date_period.py +57 -0
- numdaplot/dates/duration_in.py +58 -0
- numdaplot/dates/duration_unit.py +90 -0
- numdaplot/dates/period_unit.py +101 -0
- numdaplot/dates/time_function.py +56 -0
- numdaplot/dates/time_zone.py +68 -0
- numdaplot/dates/time_zone_change.py +71 -0
- numdaplot/dates/time_zone_mode.py +81 -0
- numdaplot/dates/to_duration.py +58 -0
- numdaplot/errors/__init__.py +7 -0
- numdaplot/errors/broadcast_warning.py +36 -0
- numdaplot/errors/calculation_warning.py +35 -0
- numdaplot/errors/cell_out_of_range_error.py +77 -0
- numdaplot/errors/column_not_found_error.py +64 -0
- numdaplot/errors/conflicting_settings_error.py +60 -0
- numdaplot/errors/dimension_error.py +62 -0
- numdaplot/errors/display_warning.py +32 -0
- numdaplot/errors/duplicate_column_error.py +82 -0
- numdaplot/errors/duplicate_label_error.py +55 -0
- numdaplot/errors/duplicate_statistic_error.py +55 -0
- numdaplot/errors/duplicate_value_error.py +54 -0
- numdaplot/errors/empty_array_error.py +55 -0
- numdaplot/errors/empty_list_error.py +52 -0
- numdaplot/errors/empty_region_error.py +34 -0
- numdaplot/errors/empty_text_error.py +34 -0
- numdaplot/errors/empty_total_error.py +62 -0
- numdaplot/errors/empty_values_error.py +34 -0
- numdaplot/errors/file_access_error.py +70 -0
- numdaplot/errors/file_exists_error.py +62 -0
- numdaplot/errors/file_not_found_error.py +56 -0
- numdaplot/errors/incompatible_charts_error.py +80 -0
- numdaplot/errors/incompatible_types_error.py +104 -0
- numdaplot/errors/integer_overflow_error.py +61 -0
- numdaplot/errors/invalid_base_error.py +52 -0
- numdaplot/errors/invalid_bin_width_error.py +66 -0
- numdaplot/errors/invalid_bounds_error.py +58 -0
- numdaplot/errors/invalid_chart_data_error.py +81 -0
- numdaplot/errors/invalid_color_count_error.py +63 -0
- numdaplot/errors/invalid_color_error.py +51 -0
- numdaplot/errors/invalid_column_name_error.py +52 -0
- numdaplot/errors/invalid_conversion_error.py +119 -0
- numdaplot/errors/invalid_count_error.py +61 -0
- numdaplot/errors/invalid_date_format_error.py +51 -0
- numdaplot/errors/invalid_deviation_error.py +52 -0
- numdaplot/errors/invalid_fraction_error.py +51 -0
- numdaplot/errors/invalid_label_count_error.py +61 -0
- numdaplot/errors/invalid_limits_error.py +111 -0
- numdaplot/errors/invalid_opacity_error.py +52 -0
- numdaplot/errors/invalid_point_size_error.py +52 -0
- numdaplot/errors/invalid_position_error.py +106 -0
- numdaplot/errors/invalid_resolution_error.py +51 -0
- numdaplot/errors/invalid_rotation_error.py +53 -0
- numdaplot/errors/invalid_seed_error.py +53 -0
- numdaplot/errors/invalid_separator_error.py +52 -0
- numdaplot/errors/invalid_shape_error.py +52 -0
- numdaplot/errors/invalid_sheet_name_error.py +54 -0
- numdaplot/errors/invalid_size_error.py +58 -0
- numdaplot/errors/invalid_step_error.py +77 -0
- numdaplot/errors/invalid_suffixes_error.py +61 -0
- numdaplot/errors/invalid_time_zone_change_error.py +63 -0
- numdaplot/errors/invalid_type_error.py +79 -0
- numdaplot/errors/irregular_list_error.py +36 -0
- numdaplot/errors/join_relation_error.py +183 -0
- numdaplot/errors/missing_dependency_error.py +58 -0
- numdaplot/errors/missing_type_error.py +36 -0
- numdaplot/errors/missing_value_error.py +62 -0
- numdaplot/errors/not_single_value_error.py +53 -0
- numdaplot/errors/numdaplot_error.py +25 -0
- numdaplot/errors/numdaplot_warning.py +34 -0
- numdaplot/errors/occupied_cell_error.py +63 -0
- numdaplot/errors/out_of_domain_error.py +70 -0
- numdaplot/errors/readability_warning.py +35 -0
- numdaplot/errors/refused_operation_error.py +64 -0
- numdaplot/errors/refused_setting_error.py +60 -0
- numdaplot/errors/rejected_dates.py +60 -0
- numdaplot/errors/repeated_key.py +36 -0
- numdaplot/errors/shape_mismatch_error.py +67 -0
- numdaplot/errors/time_overflow_error.py +131 -0
- numdaplot/errors/time_zone_mismatch_error.py +83 -0
- numdaplot/errors/unknown_time_zone_error.py +51 -0
- numdaplot/errors/unmatched_value_error.py +81 -0
- numdaplot/errors/unsupported_image_format_error.py +56 -0
- numdaplot/errors/unsupported_index_error.py +38 -0
- numdaplot/errors/unsupported_missing_error.py +129 -0
- numdaplot/errors/unsupported_type_error.py +62 -0
- numdaplot/errors/value_conversion_error.py +215 -0
- numdaplot/ordering/__init__.py +5 -0
- numdaplot/ordering/missing_position.py +46 -0
- numdaplot/ordering/order.py +46 -0
- numdaplot/package_version.py +36 -0
- numdaplot/plots/__init__.py +5 -0
- numdaplot/plots/chart_layer.py +47 -0
- numdaplot/plots/charts/__init__.py +5 -0
- numdaplot/plots/charts/bar_chart.py +98 -0
- numdaplot/plots/charts/bar_layout.py +58 -0
- numdaplot/plots/charts/bin_count.py +61 -0
- numdaplot/plots/charts/bin_width.py +78 -0
- numdaplot/plots/charts/box_chart.py +97 -0
- numdaplot/plots/charts/cell_values.py +61 -0
- numdaplot/plots/charts/chart.py +59 -0
- numdaplot/plots/charts/chart_settings.py +105 -0
- numdaplot/plots/charts/color_scale.py +147 -0
- numdaplot/plots/charts/heatmap_chart.py +92 -0
- numdaplot/plots/charts/histogram_chart.py +93 -0
- numdaplot/plots/charts/line_chart.py +100 -0
- numdaplot/plots/charts/line_type.py +75 -0
- numdaplot/plots/charts/marker_shape.py +113 -0
- numdaplot/plots/charts/missing_chart.py +60 -0
- numdaplot/plots/charts/missing_map_chart.py +27 -0
- numdaplot/plots/charts/orientation.py +58 -0
- numdaplot/plots/charts/outliers.py +49 -0
- numdaplot/plots/charts/percentages.py +55 -0
- numdaplot/plots/charts/pie_chart.py +87 -0
- numdaplot/plots/charts/scatter_chart.py +159 -0
- numdaplot/plots/charts/value_axis.py +66 -0
- numdaplot/plots/data/__init__.py +5 -0
- numdaplot/plots/data/array_values.py +128 -0
- numdaplot/plots/data/chart_data.py +143 -0
- numdaplot/plots/data/chart_values.py +109 -0
- numdaplot/plots/data/column_reading.py +468 -0
- numdaplot/plots/data/heatmap_values.py +63 -0
- numdaplot/plots/data/missing_cells.py +165 -0
- numdaplot/plots/data/pie_values.py +215 -0
- numdaplot/plots/data/point_values.py +249 -0
- numdaplot/plots/data/position_kind.py +83 -0
- numdaplot/plots/data/renamed_layers.py +340 -0
- numdaplot/plots/data/sample_values.py +160 -0
- numdaplot/plots/data/shown_columns.py +248 -0
- numdaplot/plots/data/table_values.py +256 -0
- numdaplot/plots/data/unique_labels.py +45 -0
- numdaplot/plots/drawing/__init__.py +5 -0
- numdaplot/plots/drawing/bar_drawing.py +316 -0
- numdaplot/plots/drawing/box_drawing.py +344 -0
- numdaplot/plots/drawing/cell_merging.py +237 -0
- numdaplot/plots/drawing/chart_texts.py +124 -0
- numdaplot/plots/drawing/color_bar.py +57 -0
- numdaplot/plots/drawing/color_scale_values.py +120 -0
- numdaplot/plots/drawing/default_labels.py +41 -0
- numdaplot/plots/drawing/drawn_chart.py +50 -0
- numdaplot/plots/drawing/grid_axes.py +75 -0
- numdaplot/plots/drawing/heatmap_drawing.py +313 -0
- numdaplot/plots/drawing/histogram_drawing.py +350 -0
- numdaplot/plots/drawing/label_room.py +344 -0
- numdaplot/plots/drawing/label_thinning.py +216 -0
- numdaplot/plots/drawing/layer_alignment.py +319 -0
- numdaplot/plots/drawing/layer_colors.py +123 -0
- numdaplot/plots/drawing/line_drawing.py +85 -0
- numdaplot/plots/drawing/marker_codes.py +20 -0
- numdaplot/plots/drawing/missing_drawing.py +360 -0
- numdaplot/plots/drawing/moment_period_formatter.py +253 -0
- numdaplot/plots/drawing/pie_drawing.py +185 -0
- numdaplot/plots/drawing/plot_axes.py +38 -0
- numdaplot/plots/drawing/plot_drawing.py +288 -0
- numdaplot/plots/drawing/plot_theme.py +45 -0
- numdaplot/plots/drawing/position_axis.py +278 -0
- numdaplot/plots/drawing/scatter_drawing.py +364 -0
- numdaplot/plots/drawing/series_colors.py +177 -0
- numdaplot/plots/drawing/size_inches.py +45 -0
- numdaplot/plots/drawing/style_drawing.py +410 -0
- numdaplot/plots/drawing/text_contrast.py +44 -0
- numdaplot/plots/drawing/tick_rotation.py +354 -0
- numdaplot/plots/drawing/time_axis.py +212 -0
- numdaplot/plots/drawing/whole_numbers.py +72 -0
- numdaplot/plots/figure/__init__.py +5 -0
- numdaplot/plots/figure/cell.py +95 -0
- numdaplot/plots/figure/figure.py +256 -0
- numdaplot/plots/figure/figure_drawing.py +99 -0
- numdaplot/plots/figure/figure_style.py +60 -0
- numdaplot/plots/figure/layout.py +71 -0
- numdaplot/plots/figure/placement.py +150 -0
- numdaplot/plots/layer_reading.py +166 -0
- numdaplot/plots/output/__init__.py +5 -0
- numdaplot/plots/output/image_saving.py +187 -0
- numdaplot/plots/output/plot_display.py +181 -0
- numdaplot/plots/output/shown_object.py +45 -0
- numdaplot/plots/overlay_checks.py +245 -0
- numdaplot/plots/plot.py +31 -0
- numdaplot/plots/plot_data.py +140 -0
- numdaplot/plots/plot_distribution_creation.py +237 -0
- numdaplot/plots/plot_output.py +124 -0
- numdaplot/plots/plot_overlays.py +273 -0
- numdaplot/plots/plot_overview_creation.py +195 -0
- numdaplot/plots/plot_series_creation.py +213 -0
- numdaplot/plots/style/__init__.py +5 -0
- numdaplot/plots/style/axis_settings.py +60 -0
- numdaplot/plots/style/color.py +168 -0
- numdaplot/plots/style/custom_color.py +65 -0
- numdaplot/plots/style/grid_lines.py +49 -0
- numdaplot/plots/style/image_options.py +71 -0
- numdaplot/plots/style/legend_position.py +149 -0
- numdaplot/plots/style/plot_style.py +136 -0
- numdaplot/plots/style/size.py +70 -0
- numdaplot/plots/style/size_unit.py +62 -0
- numdaplot/positions/__init__.py +5 -0
- numdaplot/positions/axis.py +54 -0
- numdaplot/positions/index.py +51 -0
- numdaplot/positions/range.py +90 -0
- numdaplot/positions/region.py +92 -0
- numdaplot/py.typed +0 -0
- numdaplot/ratios/__init__.py +5 -0
- numdaplot/ratios/fraction.py +40 -0
- numdaplot/ratios/measure.py +48 -0
- numdaplot/rules/__init__.py +5 -0
- numdaplot/rules/between.py +78 -0
- numdaplot/rules/bounds.py +83 -0
- numdaplot/rules/case.py +48 -0
- numdaplot/rules/contains.py +63 -0
- numdaplot/rules/equal.py +43 -0
- numdaplot/rules/greater.py +39 -0
- numdaplot/rules/greater_or_equal.py +38 -0
- numdaplot/rules/is_in.py +67 -0
- numdaplot/rules/is_missing.py +25 -0
- numdaplot/rules/is_present.py +25 -0
- numdaplot/rules/less.py +39 -0
- numdaplot/rules/less_or_equal.py +38 -0
- numdaplot/rules/not_equal.py +45 -0
- numdaplot/rules/rule.py +62 -0
- numdaplot/rules/rule_values.py +44 -0
- numdaplot/rules/value_rule.py +110 -0
- numdaplot/settings/__init__.py +5 -0
- numdaplot/settings/argument_types.py +327 -0
- numdaplot/settings/field_types.py +593 -0
- numdaplot/statistics/__init__.py +5 -0
- numdaplot/statistics/count.py +71 -0
- numdaplot/statistics/count_distinct.py +27 -0
- numdaplot/statistics/counted_missing.py +46 -0
- numdaplot/statistics/maximum.py +27 -0
- numdaplot/statistics/mean.py +27 -0
- numdaplot/statistics/median.py +27 -0
- numdaplot/statistics/minimum.py +27 -0
- numdaplot/statistics/most_frequent.py +27 -0
- numdaplot/statistics/most_frequent_count.py +27 -0
- numdaplot/statistics/quantile.py +61 -0
- numdaplot/statistics/standard_deviation.py +29 -0
- numdaplot/statistics/statistic.py +63 -0
- numdaplot/statistics/sum.py +27 -0
- numdaplot/tables/__init__.py +5 -0
- numdaplot/tables/aggregation/__init__.py +5 -0
- numdaplot/tables/aggregation/aggregated_frame.py +189 -0
- numdaplot/tables/aggregation/aggregation.py +97 -0
- numdaplot/tables/aggregation/calculation.py +123 -0
- numdaplot/tables/aggregation/result_column.py +108 -0
- numdaplot/tables/aggregation/row_groups.py +96 -0
- numdaplot/tables/aggregation/statistic_name.py +122 -0
- numdaplot/tables/columns/__init__.py +5 -0
- numdaplot/tables/columns/added_column.py +89 -0
- numdaplot/tables/columns/boolean_conversion.py +144 -0
- numdaplot/tables/columns/boolean_rule.py +59 -0
- numdaplot/tables/columns/bracket_end.py +50 -0
- numdaplot/tables/columns/bracket_names.py +346 -0
- numdaplot/tables/columns/bracketed_column.py +179 -0
- numdaplot/tables/columns/brackets.py +234 -0
- numdaplot/tables/columns/chosen_columns.py +55 -0
- numdaplot/tables/columns/column_choice.py +84 -0
- numdaplot/tables/columns/column_mode.py +64 -0
- numdaplot/tables/columns/column_names.py +186 -0
- numdaplot/tables/columns/conversion.py +103 -0
- numdaplot/tables/columns/converted_column.py +669 -0
- numdaplot/tables/columns/date_conversion.py +526 -0
- numdaplot/tables/columns/date_range.py +135 -0
- numdaplot/tables/columns/name_change.py +67 -0
- numdaplot/tables/columns/new_column.py +79 -0
- numdaplot/tables/columns/number_conversion.py +281 -0
- numdaplot/tables/columns/renamed_columns.py +60 -0
- numdaplot/tables/columns/renaming.py +81 -0
- numdaplot/tables/columns/text_conversion.py +70 -0
- numdaplot/tables/columns/time_conversion.py +313 -0
- numdaplot/tables/columns/time_zone_conversion.py +128 -0
- numdaplot/tables/conflict.py +68 -0
- numdaplot/tables/description/__init__.py +5 -0
- numdaplot/tables/description/described_frame.py +335 -0
- numdaplot/tables/description/description.py +155 -0
- numdaplot/tables/duplicates/__init__.py +5 -0
- numdaplot/tables/duplicates/deduplicated_frame.py +66 -0
- numdaplot/tables/duplicates/deduplication.py +88 -0
- numdaplot/tables/duplicates/keep.py +81 -0
- numdaplot/tables/files/__init__.py +5 -0
- numdaplot/tables/files/column_names.py +60 -0
- numdaplot/tables/files/csv_file.py +265 -0
- numdaplot/tables/files/csv_read_options.py +89 -0
- numdaplot/tables/files/csv_separator.py +41 -0
- numdaplot/tables/files/csv_write_options.py +79 -0
- numdaplot/tables/files/decimal_count.py +42 -0
- numdaplot/tables/files/encoding.py +82 -0
- numdaplot/tables/files/excel_file.py +171 -0
- numdaplot/tables/files/excel_read_options.py +79 -0
- numdaplot/tables/files/excel_sheet.py +50 -0
- numdaplot/tables/files/excel_time_cells.py +146 -0
- numdaplot/tables/files/excel_write_options.py +63 -0
- numdaplot/tables/files/file_access.py +152 -0
- numdaplot/tables/files/file_paths.py +106 -0
- numdaplot/tables/files/json_decimals.py +387 -0
- numdaplot/tables/files/json_file.py +203 -0
- numdaplot/tables/files/json_layout.py +63 -0
- numdaplot/tables/files/json_read_options.py +64 -0
- numdaplot/tables/files/json_write_options.py +71 -0
- numdaplot/tables/files/missing_texts.py +63 -0
- numdaplot/tables/files/optional_package.py +42 -0
- numdaplot/tables/files/pandas_backend.py +11 -0
- numdaplot/tables/files/parquet_file.py +91 -0
- numdaplot/tables/files/parquet_read_options.py +56 -0
- numdaplot/tables/files/sas_file.py +94 -0
- numdaplot/tables/files/sas_read_options.py +67 -0
- numdaplot/tables/files/stata_file.py +83 -0
- numdaplot/tables/files/stata_read_options.py +56 -0
- numdaplot/tables/files/xpt_read_options.py +65 -0
- numdaplot/tables/filtering/__init__.py +5 -0
- numdaplot/tables/filtering/checked_frame.py +60 -0
- numdaplot/tables/filtering/column_mask.py +71 -0
- numdaplot/tables/filtering/column_match.py +62 -0
- numdaplot/tables/filtering/condition.py +94 -0
- numdaplot/tables/filtering/filter.py +74 -0
- numdaplot/tables/filtering/filter_mode.py +67 -0
- numdaplot/tables/filtering/row_mask.py +152 -0
- numdaplot/tables/filtering/rule_moments.py +164 -0
- numdaplot/tables/frames/__init__.py +5 -0
- numdaplot/tables/frames/array_frame.py +95 -0
- numdaplot/tables/frames/cleaned_names.py +132 -0
- numdaplot/tables/frames/column.py +15 -0
- numdaplot/tables/frames/column_values.py +273 -0
- numdaplot/tables/frames/frame_equality.py +130 -0
- numdaplot/tables/frames/frame_normalization.py +459 -0
- numdaplot/tables/frames/named_column_errors.py +85 -0
- numdaplot/tables/frames/pandas_decimals.py +113 -0
- numdaplot/tables/frames/region_positions.py +113 -0
- numdaplot/tables/frames/table_text.py +222 -0
- numdaplot/tables/frames/time_columns.py +345 -0
- numdaplot/tables/frames/time_range_errors.py +117 -0
- numdaplot/tables/frames/time_zones.py +271 -0
- numdaplot/tables/joining/__init__.py +5 -0
- numdaplot/tables/joining/join.py +110 -0
- numdaplot/tables/joining/join_keys.py +367 -0
- numdaplot/tables/joining/join_mode.py +93 -0
- numdaplot/tables/joining/join_relation.py +149 -0
- numdaplot/tables/joining/join_suffixes.py +71 -0
- numdaplot/tables/joining/joined_frame.py +166 -0
- numdaplot/tables/joining/joined_names.py +107 -0
- numdaplot/tables/joining/joined_rows.py +235 -0
- numdaplot/tables/joining/key_types.py +57 -0
- numdaplot/tables/joining/relation.py +78 -0
- numdaplot/tables/missing/__init__.py +5 -0
- numdaplot/tables/missing/missing_count.py +59 -0
- numdaplot/tables/missing/missing_counts.py +214 -0
- numdaplot/tables/missing/missing_drop.py +98 -0
- numdaplot/tables/missing/missing_mode.py +63 -0
- numdaplot/tables/missing/missing_ratio.py +71 -0
- numdaplot/tables/missing/missing_removal.py +257 -0
- numdaplot/tables/missing/missing_summary.py +174 -0
- numdaplot/tables/missing/ratio_comparison.py +70 -0
- numdaplot/tables/pivot/__init__.py +5 -0
- numdaplot/tables/pivot/pivot_table.py +104 -0
- numdaplot/tables/pivot/pivoted_frame.py +244 -0
- numdaplot/tables/preview/__init__.py +5 -0
- numdaplot/tables/preview/notebook_display.py +238 -0
- numdaplot/tables/preview/preview.py +100 -0
- numdaplot/tables/preview/preview_rows.py +55 -0
- numdaplot/tables/preview/shown_columns.py +62 -0
- numdaplot/tables/preview/side.py +82 -0
- numdaplot/tables/sorting/__init__.py +5 -0
- numdaplot/tables/sorting/sort_key.py +71 -0
- numdaplot/tables/sorting/sorted_frame.py +81 -0
- numdaplot/tables/sorting/sorting.py +82 -0
- numdaplot/tables/table.py +71 -0
- numdaplot/tables/table_calculation.py +172 -0
- numdaplot/tables/table_columns.py +214 -0
- numdaplot/tables/table_conversion.py +351 -0
- numdaplot/tables/table_data.py +321 -0
- numdaplot/tables/table_display.py +56 -0
- numdaplot/tables/table_joining.py +80 -0
- numdaplot/tables/table_layout.py +105 -0
- numdaplot/tables/table_missing.py +146 -0
- numdaplot/tables/table_reading.py +451 -0
- numdaplot/tables/table_refusals.py +295 -0
- numdaplot/tables/table_selection.py +163 -0
- numdaplot/tables/table_writing.py +269 -0
- numdaplot-0.1.0.dist-info/METADATA +176 -0
- numdaplot-0.1.0.dist-info/RECORD +474 -0
- numdaplot-0.1.0.dist-info/WHEEL +4 -0
- numdaplot-0.1.0.dist-info/licenses/LICENSE +28 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Drawing of a BarChart.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# The matplotlib stubs leave the keyword arguments of most drawing methods untyped.
|
|
8
|
+
# pyright: reportUnknownMemberType=false
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from typing import cast
|
|
12
|
+
|
|
13
|
+
import numpy
|
|
14
|
+
from matplotlib.axes import Axes
|
|
15
|
+
from numpy.typing import NDArray
|
|
16
|
+
|
|
17
|
+
from numdaplot.plots.chart_layer import ChartLayer
|
|
18
|
+
from numdaplot.plots.charts.bar_chart import BarChart
|
|
19
|
+
from numdaplot.plots.charts.bar_layout import BarLayout
|
|
20
|
+
from numdaplot.plots.charts.orientation import Orientation
|
|
21
|
+
from numdaplot.plots.data.chart_values import ChartValues
|
|
22
|
+
from numdaplot.plots.drawing.default_labels import find_position_label
|
|
23
|
+
from numdaplot.plots.drawing.drawn_chart import DrawnChart
|
|
24
|
+
from numdaplot.plots.drawing.grid_axes import GridAxes
|
|
25
|
+
from numdaplot.plots.drawing.position_axis import place_categories
|
|
26
|
+
from numdaplot.plots.drawing.series_colors import choose_series_colors
|
|
27
|
+
|
|
28
|
+
GROUP_WIDTH = 0.8
|
|
29
|
+
HALF = 0.5
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass(frozen=True)
|
|
33
|
+
class BarStyle:
|
|
34
|
+
"""
|
|
35
|
+
The look of the bars of one series.
|
|
36
|
+
|
|
37
|
+
.. versionadded:: 0.1.0
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
thickness
|
|
42
|
+
The thickness of each bar, a position being 1 wide.
|
|
43
|
+
color_code
|
|
44
|
+
The ``#rrggbb`` code of the bars.
|
|
45
|
+
|
|
46
|
+
Examples
|
|
47
|
+
--------
|
|
48
|
+
>>> from numdaplot.plots.drawing.bar_drawing import BarStyle
|
|
49
|
+
>>> BarStyle(0.4, "#1f77b4").thickness
|
|
50
|
+
0.4
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
thickness: float
|
|
54
|
+
color_code: str
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass(frozen=True, eq=False)
|
|
58
|
+
class BarSeries:
|
|
59
|
+
"""
|
|
60
|
+
The bars of one series, ready to be drawn.
|
|
61
|
+
|
|
62
|
+
.. versionadded:: 0.1.0
|
|
63
|
+
|
|
64
|
+
Parameters
|
|
65
|
+
----------
|
|
66
|
+
name
|
|
67
|
+
The name shown in the legend.
|
|
68
|
+
coordinates
|
|
69
|
+
The coordinate of the middle of each bar along the axis of the ``x`` values.
|
|
70
|
+
lengths
|
|
71
|
+
The length of each bar, NaN for a missing value, which draws no bar.
|
|
72
|
+
bases
|
|
73
|
+
Where each bar starts along the axis of the values: 0, or the top of the bars below it when stacked.
|
|
74
|
+
style
|
|
75
|
+
The thickness of the bars and their color code.
|
|
76
|
+
|
|
77
|
+
Examples
|
|
78
|
+
--------
|
|
79
|
+
>>> import numpy
|
|
80
|
+
>>> from numdaplot.plots.drawing.bar_drawing import BarSeries, BarStyle
|
|
81
|
+
>>> BarSeries("price", numpy.array([0.0]), numpy.array([12.0]), numpy.array([0.0]), BarStyle(0.8, "#1f77b4")).name
|
|
82
|
+
'price'
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
name: str
|
|
86
|
+
coordinates: NDArray[numpy.float64]
|
|
87
|
+
lengths: NDArray[numpy.float64]
|
|
88
|
+
bases: NDArray[numpy.float64]
|
|
89
|
+
style: BarStyle
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@dataclass(frozen=True, eq=False)
|
|
93
|
+
class StackTops:
|
|
94
|
+
"""
|
|
95
|
+
Where the next stacked bar starts at each position, above zero and below zero.
|
|
96
|
+
|
|
97
|
+
.. versionadded:: 0.1.0
|
|
98
|
+
|
|
99
|
+
Parameters
|
|
100
|
+
----------
|
|
101
|
+
positive
|
|
102
|
+
The top of the positive bars already stacked.
|
|
103
|
+
negative
|
|
104
|
+
The bottom of the negative bars already stacked.
|
|
105
|
+
|
|
106
|
+
Examples
|
|
107
|
+
--------
|
|
108
|
+
>>> import numpy
|
|
109
|
+
>>> from numdaplot.plots.drawing.bar_drawing import StackTops
|
|
110
|
+
>>> StackTops(numpy.zeros(2), numpy.zeros(2)).positive
|
|
111
|
+
array([0., 0.])
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
positive: NDArray[numpy.float64]
|
|
115
|
+
negative: NDArray[numpy.float64]
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def draw_bar_chart(axes: Axes, layer: ChartLayer) -> DrawnChart:
|
|
119
|
+
"""
|
|
120
|
+
Draw each series of a BarChart as bars, one position per ``x`` value.
|
|
121
|
+
|
|
122
|
+
A missing value draws no bar. Horizontal bars are drawn from the top, in the order of the rows.
|
|
123
|
+
|
|
124
|
+
.. versionadded:: 0.1.0
|
|
125
|
+
|
|
126
|
+
Parameters
|
|
127
|
+
----------
|
|
128
|
+
axes
|
|
129
|
+
The matplotlib axes drawn on.
|
|
130
|
+
layer
|
|
131
|
+
A BarChart and its values.
|
|
132
|
+
|
|
133
|
+
Returns
|
|
134
|
+
-------
|
|
135
|
+
DrawnChart
|
|
136
|
+
The default labels, where the ``x`` values are, and grid lines across the axis of the values only.
|
|
137
|
+
|
|
138
|
+
Raises
|
|
139
|
+
------
|
|
140
|
+
InvalidColorCountError
|
|
141
|
+
When the colors of the chart are not one per series.
|
|
142
|
+
|
|
143
|
+
Examples
|
|
144
|
+
--------
|
|
145
|
+
>>> import numdaplot as ndp
|
|
146
|
+
>>> from matplotlib.figure import Figure
|
|
147
|
+
>>> from numdaplot.plots.chart_layer import ChartLayer
|
|
148
|
+
>>> from numdaplot.plots.data.array_values import read_array_values
|
|
149
|
+
>>> from numdaplot.plots.drawing.bar_drawing import draw_bar_chart
|
|
150
|
+
>>> prices = ndp.Array.from_list([12.0, None, 15.5])
|
|
151
|
+
>>> axes = Figure().add_subplot()
|
|
152
|
+
>>> drawn_chart = draw_bar_chart(axes, ChartLayer(ndp.BarChart(), read_array_values(prices, "BarChart")))
|
|
153
|
+
>>> [float(bar.get_height()) for bar in axes.patches]
|
|
154
|
+
[12.0, 15.5]
|
|
155
|
+
"""
|
|
156
|
+
chart = cast(BarChart, layer.chart)
|
|
157
|
+
values = cast(ChartValues, layer.values)
|
|
158
|
+
series_count = len(values.series)
|
|
159
|
+
color_codes = choose_series_colors(chart.colors, series_count)
|
|
160
|
+
is_horizontal = chart.orientation == Orientation.HORIZONTAL
|
|
161
|
+
is_stacked = chart.layout == BarLayout.STACKED
|
|
162
|
+
coordinates = place_categories(axes, values.positions, is_horizontal)
|
|
163
|
+
position_count = len(coordinates)
|
|
164
|
+
stack_tops = StackTops(numpy.zeros(position_count), numpy.zeros(position_count))
|
|
165
|
+
bases = numpy.zeros(position_count)
|
|
166
|
+
thickness = GROUP_WIDTH / series_count
|
|
167
|
+
if is_stacked:
|
|
168
|
+
thickness = GROUP_WIDTH
|
|
169
|
+
|
|
170
|
+
for i, series in enumerate(values.series):
|
|
171
|
+
bar_coordinates = find_group_coordinates(coordinates, i, series_count)
|
|
172
|
+
if is_stacked:
|
|
173
|
+
bar_coordinates = coordinates
|
|
174
|
+
bases, stack_tops = stack_bars(series.values, stack_tops)
|
|
175
|
+
|
|
176
|
+
bar_style = BarStyle(thickness, color_codes[i])
|
|
177
|
+
bar_series = BarSeries(series.name, bar_coordinates, series.values, bases, bar_style)
|
|
178
|
+
draw_series_bars(axes, bar_series, is_horizontal)
|
|
179
|
+
|
|
180
|
+
if is_horizontal:
|
|
181
|
+
axes.invert_yaxis()
|
|
182
|
+
|
|
183
|
+
x_label = find_position_label(values.positions)
|
|
184
|
+
drawn_chart = DrawnChart(x_label, values.value_name, is_horizontal, GridAxes.VALUES, None)
|
|
185
|
+
|
|
186
|
+
return drawn_chart
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def find_group_coordinates(
|
|
190
|
+
coordinates: NDArray[numpy.float64], series_number: int, series_count: int
|
|
191
|
+
) -> NDArray[numpy.float64]:
|
|
192
|
+
"""
|
|
193
|
+
Return the middle of the bars of one series when the series are side by side.
|
|
194
|
+
|
|
195
|
+
.. versionadded:: 0.1.0
|
|
196
|
+
|
|
197
|
+
Parameters
|
|
198
|
+
----------
|
|
199
|
+
coordinates
|
|
200
|
+
The middle of each position.
|
|
201
|
+
series_number
|
|
202
|
+
The number of the series, from 0.
|
|
203
|
+
series_count
|
|
204
|
+
The number of series sharing each position.
|
|
205
|
+
|
|
206
|
+
Returns
|
|
207
|
+
-------
|
|
208
|
+
NDArray[numpy.float64]
|
|
209
|
+
The middle of each bar of the series.
|
|
210
|
+
|
|
211
|
+
Examples
|
|
212
|
+
--------
|
|
213
|
+
>>> import numpy
|
|
214
|
+
>>> from numdaplot.plots.drawing.bar_drawing import find_group_coordinates
|
|
215
|
+
>>> find_group_coordinates(numpy.array([0.0, 1.0]), 0, 2)
|
|
216
|
+
array([-0.2, 0.8])
|
|
217
|
+
"""
|
|
218
|
+
thickness = GROUP_WIDTH / series_count
|
|
219
|
+
middle_number = series_number + HALF
|
|
220
|
+
group_offset = middle_number * thickness
|
|
221
|
+
group_start = GROUP_WIDTH * HALF
|
|
222
|
+
offset = group_offset - group_start
|
|
223
|
+
shifted_coordinates = coordinates + offset
|
|
224
|
+
# Some versions of the numpy stubs widen the sum of float64 values to any floating type.
|
|
225
|
+
group_coordinates = numpy.asarray(shifted_coordinates, dtype=numpy.float64)
|
|
226
|
+
|
|
227
|
+
return group_coordinates
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def stack_bars(lengths: NDArray[numpy.float64], stack_tops: StackTops) -> tuple[NDArray[numpy.float64], StackTops]:
|
|
231
|
+
"""
|
|
232
|
+
Return where the bars of a series start when stacked, and the tops of the stacks once they are added.
|
|
233
|
+
|
|
234
|
+
Positive values stack above zero and negative values below it. A missing value adds nothing.
|
|
235
|
+
|
|
236
|
+
.. versionadded:: 0.1.0
|
|
237
|
+
|
|
238
|
+
Parameters
|
|
239
|
+
----------
|
|
240
|
+
lengths
|
|
241
|
+
The values of the series, NaN where a value is missing.
|
|
242
|
+
stack_tops
|
|
243
|
+
The tops of the stacks before this series.
|
|
244
|
+
|
|
245
|
+
Returns
|
|
246
|
+
-------
|
|
247
|
+
tuple[NDArray[numpy.float64], StackTops]
|
|
248
|
+
The base of each bar, and the new tops.
|
|
249
|
+
|
|
250
|
+
Examples
|
|
251
|
+
--------
|
|
252
|
+
>>> import numpy
|
|
253
|
+
>>> from numdaplot.plots.drawing.bar_drawing import StackTops, stack_bars
|
|
254
|
+
>>> bases, stack_tops = stack_bars(numpy.array([2.0, -1.0]), StackTops(numpy.array([1.0, 1.0]), numpy.zeros(2)))
|
|
255
|
+
>>> bases
|
|
256
|
+
array([1., 0.])
|
|
257
|
+
>>> stack_tops.positive
|
|
258
|
+
array([3., 1.])
|
|
259
|
+
"""
|
|
260
|
+
present_lengths = numpy.nan_to_num(lengths)
|
|
261
|
+
is_positive = present_lengths >= 0
|
|
262
|
+
bases = numpy.where(is_positive, stack_tops.positive, stack_tops.negative)
|
|
263
|
+
tops = bases + present_lengths
|
|
264
|
+
positive_tops = numpy.where(is_positive, tops, stack_tops.positive)
|
|
265
|
+
negative_tops = numpy.where(is_positive, stack_tops.negative, tops)
|
|
266
|
+
new_tops = StackTops(positive_tops, negative_tops)
|
|
267
|
+
|
|
268
|
+
return bases, new_tops
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def draw_series_bars(axes: Axes, bar_series: BarSeries, is_horizontal: bool) -> None:
|
|
272
|
+
"""
|
|
273
|
+
Draw the bars of one series, except at its missing values.
|
|
274
|
+
|
|
275
|
+
.. versionadded:: 0.1.0
|
|
276
|
+
|
|
277
|
+
Parameters
|
|
278
|
+
----------
|
|
279
|
+
axes
|
|
280
|
+
The matplotlib axes drawn on.
|
|
281
|
+
bar_series
|
|
282
|
+
The bars of the series.
|
|
283
|
+
is_horizontal
|
|
284
|
+
True to draw horizontal bars.
|
|
285
|
+
|
|
286
|
+
Examples
|
|
287
|
+
--------
|
|
288
|
+
>>> import numpy
|
|
289
|
+
>>> from matplotlib.figure import Figure
|
|
290
|
+
>>> from numdaplot.plots.drawing.bar_drawing import BarSeries, BarStyle, draw_series_bars
|
|
291
|
+
>>> axes = Figure().add_subplot()
|
|
292
|
+
>>> bar_style = BarStyle(0.8, "#1f77b4")
|
|
293
|
+
>>> bar_series = BarSeries("price", numpy.arange(2.0), numpy.array([3.0, 4.0]), numpy.zeros(2), bar_style)
|
|
294
|
+
>>> draw_series_bars(axes, bar_series, True)
|
|
295
|
+
>>> [float(bar.get_width()) for bar in axes.patches]
|
|
296
|
+
[3.0, 4.0]
|
|
297
|
+
"""
|
|
298
|
+
is_present = ~numpy.isnan(bar_series.lengths)
|
|
299
|
+
coordinates = bar_series.coordinates[is_present]
|
|
300
|
+
lengths = bar_series.lengths[is_present]
|
|
301
|
+
bases = bar_series.bases[is_present]
|
|
302
|
+
bar_style = bar_series.style
|
|
303
|
+
if is_horizontal:
|
|
304
|
+
axes.barh(
|
|
305
|
+
coordinates,
|
|
306
|
+
lengths,
|
|
307
|
+
height=bar_style.thickness,
|
|
308
|
+
left=bases,
|
|
309
|
+
color=bar_style.color_code,
|
|
310
|
+
label=bar_series.name,
|
|
311
|
+
)
|
|
312
|
+
return
|
|
313
|
+
|
|
314
|
+
axes.bar(
|
|
315
|
+
coordinates, lengths, width=bar_style.thickness, bottom=bases, color=bar_style.color_code, label=bar_series.name
|
|
316
|
+
)
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Drawing of a BoxChart.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# The matplotlib stubs leave the keyword arguments of most drawing methods untyped.
|
|
8
|
+
# pyright: reportUnknownMemberType=false
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from typing import Any, cast
|
|
12
|
+
|
|
13
|
+
import numpy
|
|
14
|
+
import pandas
|
|
15
|
+
from matplotlib.axes import Axes
|
|
16
|
+
from numpy.typing import NDArray
|
|
17
|
+
|
|
18
|
+
from numdaplot.plots.chart_layer import ChartLayer
|
|
19
|
+
from numdaplot.plots.charts.box_chart import BoxChart
|
|
20
|
+
from numdaplot.plots.charts.outliers import Outliers
|
|
21
|
+
from numdaplot.plots.data.chart_values import Positions, Series
|
|
22
|
+
from numdaplot.plots.data.position_kind import PositionKind
|
|
23
|
+
from numdaplot.plots.data.sample_values import SampleValues, drop_missing_numbers
|
|
24
|
+
from numdaplot.plots.drawing.bar_drawing import GROUP_WIDTH, find_group_coordinates
|
|
25
|
+
from numdaplot.plots.drawing.default_labels import COLUMN_LABEL
|
|
26
|
+
from numdaplot.plots.drawing.drawn_chart import DrawnChart
|
|
27
|
+
from numdaplot.plots.drawing.grid_axes import GridAxes
|
|
28
|
+
from numdaplot.plots.drawing.plot_theme import BACKGROUND_COLOR
|
|
29
|
+
from numdaplot.plots.drawing.position_axis import place_categories
|
|
30
|
+
from numdaplot.plots.drawing.series_colors import choose_series_colors
|
|
31
|
+
from numdaplot.plots.drawing.time_axis import measures_times, place_hour_ticks
|
|
32
|
+
|
|
33
|
+
# Share of its place a box fills, leaving a gap between two boxes side by side.
|
|
34
|
+
BOX_SHARE = 0.8
|
|
35
|
+
# Width of a box alone at its position, a position being 1 wide.
|
|
36
|
+
COLUMN_BOX_WIDTH = 0.5
|
|
37
|
+
HALF_POSITION = 0.5
|
|
38
|
+
MEDIAN_LINE_WIDTH = 1.5
|
|
39
|
+
OUTLIER_MARKER = "o"
|
|
40
|
+
OUTLIER_SIZE = 4.0
|
|
41
|
+
TEXT_DTYPE = numpy.dtype(object)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass(frozen=True)
|
|
45
|
+
class BoxLook:
|
|
46
|
+
"""
|
|
47
|
+
The look shared by the boxes of one column.
|
|
48
|
+
|
|
49
|
+
.. versionadded:: 0.1.0
|
|
50
|
+
|
|
51
|
+
Parameters
|
|
52
|
+
----------
|
|
53
|
+
color_code
|
|
54
|
+
The ``#rrggbb`` code of the boxes.
|
|
55
|
+
width
|
|
56
|
+
The width of each box, a position being 1 wide.
|
|
57
|
+
shows_outliers
|
|
58
|
+
True to draw the outliers.
|
|
59
|
+
label
|
|
60
|
+
The name shown in the legend, or None to leave the boxes out of it.
|
|
61
|
+
|
|
62
|
+
Examples
|
|
63
|
+
--------
|
|
64
|
+
>>> from numdaplot.plots.drawing.box_drawing import BoxLook
|
|
65
|
+
>>> BoxLook("#1f77b4", 0.8, True, None).width
|
|
66
|
+
0.8
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
color_code: str
|
|
70
|
+
width: float
|
|
71
|
+
shows_outliers: bool
|
|
72
|
+
label: str | None
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def draw_box_chart(axes: Axes, layer: ChartLayer) -> DrawnChart:
|
|
76
|
+
"""
|
|
77
|
+
Draw the values of each column as a box, one per column, or one per column side by side in each group.
|
|
78
|
+
|
|
79
|
+
Each position is 1 wide, with half a position of margin at both ends, as for bars.
|
|
80
|
+
|
|
81
|
+
.. versionadded:: 0.1.0
|
|
82
|
+
|
|
83
|
+
Parameters
|
|
84
|
+
----------
|
|
85
|
+
axes
|
|
86
|
+
The matplotlib axes drawn on.
|
|
87
|
+
layer
|
|
88
|
+
A BoxChart, its columns and their groups.
|
|
89
|
+
|
|
90
|
+
Returns
|
|
91
|
+
-------
|
|
92
|
+
DrawnChart
|
|
93
|
+
The ``group_by`` column and the single column as default labels, and grid lines across the axis of the
|
|
94
|
+
values only, labeled ``HH:MM`` for times of day.
|
|
95
|
+
|
|
96
|
+
Raises
|
|
97
|
+
------
|
|
98
|
+
InvalidColorCountError
|
|
99
|
+
When the colors of the chart are not one per column.
|
|
100
|
+
|
|
101
|
+
Examples
|
|
102
|
+
--------
|
|
103
|
+
>>> import numdaplot as ndp
|
|
104
|
+
>>> from matplotlib.figure import Figure
|
|
105
|
+
>>> from numdaplot.plots.chart_layer import ChartLayer
|
|
106
|
+
>>> from numdaplot.plots.data.sample_values import read_sample_values
|
|
107
|
+
>>> from numdaplot.plots.drawing.box_drawing import draw_box_chart
|
|
108
|
+
>>> prices = ndp.Array.from_list([[12.0, 9.5], [14.0, 10.0], [13.5, 8.0]])
|
|
109
|
+
>>> axes = Figure().add_subplot()
|
|
110
|
+
>>> layer = ChartLayer(ndp.BoxChart(), read_sample_values(prices, None, None, "BoxChart"))
|
|
111
|
+
>>> drawn_chart = draw_box_chart(axes, layer)
|
|
112
|
+
>>> [label.get_text() for label in axes.get_xticklabels()]
|
|
113
|
+
['0', '1']
|
|
114
|
+
"""
|
|
115
|
+
chart = cast(BoxChart, layer.chart)
|
|
116
|
+
values = cast(SampleValues, layer.values)
|
|
117
|
+
series_count = len(values.series)
|
|
118
|
+
color_codes = choose_series_colors(chart.colors, series_count)
|
|
119
|
+
shows_outliers = chart.outliers == Outliers.SHOWN
|
|
120
|
+
if values.groups is None:
|
|
121
|
+
position_count = draw_column_boxes(axes, values.series, color_codes, shows_outliers)
|
|
122
|
+
else:
|
|
123
|
+
position_count = draw_group_boxes(axes, values, color_codes, shows_outliers)
|
|
124
|
+
|
|
125
|
+
last_edge = position_count - HALF_POSITION
|
|
126
|
+
axes.set_xlim(-HALF_POSITION, last_edge)
|
|
127
|
+
|
|
128
|
+
is_time = measures_times(values.value_type)
|
|
129
|
+
if is_time:
|
|
130
|
+
series_values = [series.values for series in values.series]
|
|
131
|
+
hours = numpy.concatenate(series_values)
|
|
132
|
+
place_hour_ticks(axes.yaxis, hours)
|
|
133
|
+
|
|
134
|
+
x_label = COLUMN_LABEL
|
|
135
|
+
if values.group_name is not None:
|
|
136
|
+
x_label = values.group_name
|
|
137
|
+
|
|
138
|
+
drawn_chart = DrawnChart(x_label, values.value_name, False, GridAxes.VALUES, None)
|
|
139
|
+
|
|
140
|
+
return drawn_chart
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def draw_column_boxes(axes: Axes, series_list: list[Series], color_codes: list[str], shows_outliers: bool) -> int:
|
|
144
|
+
"""
|
|
145
|
+
Draw one box per column, each at its own position labeled with the column name.
|
|
146
|
+
|
|
147
|
+
.. versionadded:: 0.1.0
|
|
148
|
+
|
|
149
|
+
Parameters
|
|
150
|
+
----------
|
|
151
|
+
axes
|
|
152
|
+
The matplotlib axes drawn on.
|
|
153
|
+
series_list
|
|
154
|
+
The columns drawn.
|
|
155
|
+
color_codes
|
|
156
|
+
One ``#rrggbb`` code per column.
|
|
157
|
+
shows_outliers
|
|
158
|
+
True to draw the outliers.
|
|
159
|
+
|
|
160
|
+
Returns
|
|
161
|
+
-------
|
|
162
|
+
int
|
|
163
|
+
The number of positions, one per column.
|
|
164
|
+
|
|
165
|
+
Examples
|
|
166
|
+
--------
|
|
167
|
+
>>> import numpy
|
|
168
|
+
>>> from matplotlib.figure import Figure
|
|
169
|
+
>>> from numdaplot.plots.data.chart_values import Series
|
|
170
|
+
>>> from numdaplot.plots.drawing.box_drawing import draw_column_boxes
|
|
171
|
+
>>> axes = Figure().add_subplot()
|
|
172
|
+
>>> draw_column_boxes(axes, [Series("price", numpy.array([1.0, 2.0, 4.0]))], ["#1f77b4"], True)
|
|
173
|
+
1
|
|
174
|
+
>>> [label.get_text() for label in axes.get_xticklabels()]
|
|
175
|
+
['price']
|
|
176
|
+
"""
|
|
177
|
+
column_names = [series.name for series in series_list]
|
|
178
|
+
name_values = numpy.array(column_names, dtype=TEXT_DTYPE)
|
|
179
|
+
positions = Positions(PositionKind.TEXTS, name_values, None)
|
|
180
|
+
coordinates = place_categories(axes, positions, False)
|
|
181
|
+
|
|
182
|
+
for i, series in enumerate(series_list):
|
|
183
|
+
samples = [series.values]
|
|
184
|
+
box_coordinates = coordinates[i : i + 1]
|
|
185
|
+
box_look = BoxLook(color_codes[i], COLUMN_BOX_WIDTH, shows_outliers, None)
|
|
186
|
+
draw_boxes(axes, samples, box_coordinates, box_look)
|
|
187
|
+
|
|
188
|
+
position_count = len(coordinates)
|
|
189
|
+
|
|
190
|
+
return position_count
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def draw_group_boxes(axes: Axes, values: SampleValues, color_codes: list[str], shows_outliers: bool) -> int:
|
|
194
|
+
"""
|
|
195
|
+
Draw one position per group in alphabetical order, with the boxes of the columns side by side.
|
|
196
|
+
|
|
197
|
+
Rows whose group is missing are left out. The columns are named in the legend.
|
|
198
|
+
|
|
199
|
+
.. versionadded:: 0.1.0
|
|
200
|
+
|
|
201
|
+
Parameters
|
|
202
|
+
----------
|
|
203
|
+
axes
|
|
204
|
+
The matplotlib axes drawn on.
|
|
205
|
+
values
|
|
206
|
+
The columns, the group of each row and the ``group_by`` column.
|
|
207
|
+
color_codes
|
|
208
|
+
One ``#rrggbb`` code per column.
|
|
209
|
+
shows_outliers
|
|
210
|
+
True to draw the outliers.
|
|
211
|
+
|
|
212
|
+
Returns
|
|
213
|
+
-------
|
|
214
|
+
int
|
|
215
|
+
The number of positions, one per group.
|
|
216
|
+
|
|
217
|
+
Examples
|
|
218
|
+
--------
|
|
219
|
+
>>> import numdaplot as ndp
|
|
220
|
+
>>> from matplotlib.figure import Figure
|
|
221
|
+
>>> from numdaplot.plots.data.sample_values import read_sample_values
|
|
222
|
+
>>> from numdaplot.plots.drawing.box_drawing import draw_group_boxes
|
|
223
|
+
>>> cities = ndp.Array.from_list(["Paris", "Lyon", "Paris", "Lyon"])
|
|
224
|
+
>>> prices = ndp.Array.from_list([12.0, 9.5, 14.0, 10.0])
|
|
225
|
+
>>> flats = ndp.Table.from_arrays({"city": cities, "price": prices})
|
|
226
|
+
>>> axes = Figure().add_subplot()
|
|
227
|
+
>>> draw_group_boxes(axes, read_sample_values(flats, ["price"], "city", "BoxChart"), ["#1f77b4"], True)
|
|
228
|
+
2
|
|
229
|
+
>>> [label.get_text() for label in axes.get_xticklabels()]
|
|
230
|
+
['Lyon', 'Paris']
|
|
231
|
+
"""
|
|
232
|
+
groups = cast(NDArray[Any], values.groups)
|
|
233
|
+
group_names = sort_groups(groups)
|
|
234
|
+
positions = Positions(PositionKind.TEXTS, group_names, values.group_name)
|
|
235
|
+
coordinates = place_categories(axes, positions, False)
|
|
236
|
+
series_count = len(values.series)
|
|
237
|
+
slot_width = GROUP_WIDTH / series_count
|
|
238
|
+
box_width = slot_width * BOX_SHARE
|
|
239
|
+
|
|
240
|
+
for i, series in enumerate(values.series):
|
|
241
|
+
box_coordinates = find_group_coordinates(coordinates, i, series_count)
|
|
242
|
+
samples = [series.values[groups == group_name] for group_name in group_names]
|
|
243
|
+
box_look = BoxLook(color_codes[i], box_width, shows_outliers, series.name)
|
|
244
|
+
draw_boxes(axes, samples, box_coordinates, box_look)
|
|
245
|
+
|
|
246
|
+
position_count = len(coordinates)
|
|
247
|
+
|
|
248
|
+
return position_count
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def sort_groups(groups: NDArray[Any]) -> NDArray[Any]:
|
|
252
|
+
"""
|
|
253
|
+
Return each group once, in alphabetical order, without the missing one.
|
|
254
|
+
|
|
255
|
+
.. versionadded:: 0.1.0
|
|
256
|
+
|
|
257
|
+
Parameters
|
|
258
|
+
----------
|
|
259
|
+
groups
|
|
260
|
+
The group of each row, None where it is missing.
|
|
261
|
+
|
|
262
|
+
Returns
|
|
263
|
+
-------
|
|
264
|
+
NDArray
|
|
265
|
+
The group names, in a numpy array of Python texts.
|
|
266
|
+
|
|
267
|
+
Examples
|
|
268
|
+
--------
|
|
269
|
+
>>> import numpy
|
|
270
|
+
>>> from numdaplot.plots.drawing.box_drawing import sort_groups
|
|
271
|
+
>>> sort_groups(numpy.array(["Pau", None, "Lyon", "Pau"], dtype=object))
|
|
272
|
+
array(['Lyon', 'Pau'], dtype=object)
|
|
273
|
+
"""
|
|
274
|
+
present = pandas.notna(groups)
|
|
275
|
+
present_groups = groups[present]
|
|
276
|
+
unique_groups = set[str](present_groups)
|
|
277
|
+
sorted_groups = sorted(unique_groups)
|
|
278
|
+
group_names = numpy.array(sorted_groups, dtype=TEXT_DTYPE)
|
|
279
|
+
|
|
280
|
+
return group_names
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def draw_boxes(
|
|
284
|
+
axes: Axes, samples: list[NDArray[numpy.float64]], coordinates: NDArray[numpy.float64], box_look: BoxLook
|
|
285
|
+
) -> None:
|
|
286
|
+
"""
|
|
287
|
+
Draw the boxes of one column, one per sample, skipping the samples without value.
|
|
288
|
+
|
|
289
|
+
.. versionadded:: 0.1.0
|
|
290
|
+
|
|
291
|
+
Parameters
|
|
292
|
+
----------
|
|
293
|
+
axes
|
|
294
|
+
The matplotlib axes drawn on.
|
|
295
|
+
samples
|
|
296
|
+
The numbers of each box, NaN where a value is missing.
|
|
297
|
+
coordinates
|
|
298
|
+
The middle of each box along the horizontal axis.
|
|
299
|
+
box_look
|
|
300
|
+
The color, the width, the outliers and the legend name of the boxes.
|
|
301
|
+
|
|
302
|
+
Examples
|
|
303
|
+
--------
|
|
304
|
+
>>> import numpy
|
|
305
|
+
>>> from matplotlib.figure import Figure
|
|
306
|
+
>>> from numdaplot.plots.drawing.box_drawing import BoxLook, draw_boxes
|
|
307
|
+
>>> axes = Figure().add_subplot()
|
|
308
|
+
>>> samples = [numpy.array([1.0, 2.0, 4.0]), numpy.array([numpy.nan])]
|
|
309
|
+
>>> draw_boxes(axes, samples, numpy.array([0.0, 1.0]), BoxLook("#1f77b4", 0.8, True, None))
|
|
310
|
+
>>> len(axes.patches)
|
|
311
|
+
1
|
|
312
|
+
"""
|
|
313
|
+
present_samples = [drop_missing_numbers(sample) for sample in samples]
|
|
314
|
+
drawn_numbers = [i for i, sample in enumerate(present_samples) if sample.size > 0]
|
|
315
|
+
drawn_count = len(drawn_numbers)
|
|
316
|
+
if drawn_count == 0:
|
|
317
|
+
return
|
|
318
|
+
|
|
319
|
+
drawn_samples = [present_samples[i] for i in drawn_numbers]
|
|
320
|
+
drawn_coordinates = coordinates[drawn_numbers]
|
|
321
|
+
color_code = box_look.color_code
|
|
322
|
+
box_style = {"facecolor": color_code, "edgecolor": color_code}
|
|
323
|
+
line_style = {"color": color_code}
|
|
324
|
+
median_style = {"color": BACKGROUND_COLOR, "linewidth": MEDIAN_LINE_WIDTH}
|
|
325
|
+
outlier_style = {
|
|
326
|
+
"marker": OUTLIER_MARKER,
|
|
327
|
+
"markerfacecolor": color_code,
|
|
328
|
+
"markeredgecolor": color_code,
|
|
329
|
+
"markersize": OUTLIER_SIZE,
|
|
330
|
+
}
|
|
331
|
+
axes.boxplot(
|
|
332
|
+
drawn_samples,
|
|
333
|
+
positions=drawn_coordinates,
|
|
334
|
+
widths=box_look.width,
|
|
335
|
+
patch_artist=True,
|
|
336
|
+
showfliers=box_look.shows_outliers,
|
|
337
|
+
manage_ticks=False,
|
|
338
|
+
label=box_look.label,
|
|
339
|
+
boxprops=box_style,
|
|
340
|
+
whiskerprops=line_style,
|
|
341
|
+
capprops=line_style,
|
|
342
|
+
medianprops=median_style,
|
|
343
|
+
flierprops=outlier_style,
|
|
344
|
+
)
|