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,344 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Room between the labels of an axis, and the room these labels need.
|
|
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
|
+
import heapq
|
|
11
|
+
import math
|
|
12
|
+
from typing import cast
|
|
13
|
+
|
|
14
|
+
import numpy
|
|
15
|
+
from matplotlib.axis import Axis
|
|
16
|
+
from matplotlib.figure import Figure, SubFigure
|
|
17
|
+
from matplotlib.ticker import FixedFormatter
|
|
18
|
+
from numpy.typing import NDArray
|
|
19
|
+
|
|
20
|
+
MEASURED_LABEL_COUNT = 200
|
|
21
|
+
LABEL_GAP_RATIO = 0.5
|
|
22
|
+
POINTS_PER_INCH = 72.0
|
|
23
|
+
RIGHT_ANGLE = 90.0
|
|
24
|
+
# What the layout usually leaves around the axes for the numbers and the name of the other axis.
|
|
25
|
+
LAYOUT_MARGIN_PIXELS = 60.0
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def find_tick_locations(axis: Axis) -> NDArray[numpy.float64]:
|
|
29
|
+
"""
|
|
30
|
+
Return the coordinates of the ticks of an axis.
|
|
31
|
+
|
|
32
|
+
.. versionadded:: 0.1.0
|
|
33
|
+
|
|
34
|
+
Parameters
|
|
35
|
+
----------
|
|
36
|
+
axis
|
|
37
|
+
The axis.
|
|
38
|
+
|
|
39
|
+
Returns
|
|
40
|
+
-------
|
|
41
|
+
NDArray[numpy.float64]
|
|
42
|
+
One coordinate per tick.
|
|
43
|
+
|
|
44
|
+
Examples
|
|
45
|
+
--------
|
|
46
|
+
>>> from matplotlib.figure import Figure
|
|
47
|
+
>>> from numdaplot.plots.drawing.label_room import find_tick_locations
|
|
48
|
+
>>> axes = Figure().add_subplot()
|
|
49
|
+
>>> axes.xaxis.set_ticks([0.0, 2.0]) # doctest: +ELLIPSIS
|
|
50
|
+
[...]
|
|
51
|
+
>>> find_tick_locations(axes.xaxis)
|
|
52
|
+
array([0., 2.])
|
|
53
|
+
"""
|
|
54
|
+
tick_locations = numpy.asarray(axis.get_ticklocs(), dtype=numpy.float64)
|
|
55
|
+
|
|
56
|
+
return tick_locations
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def read_label_texts(axis: Axis) -> list[str]:
|
|
60
|
+
"""
|
|
61
|
+
Return the text of each label of an axis, without creating the ticks of labels placed by ``set_fixed_labels``.
|
|
62
|
+
|
|
63
|
+
.. versionadded:: 0.1.0
|
|
64
|
+
|
|
65
|
+
Parameters
|
|
66
|
+
----------
|
|
67
|
+
axis
|
|
68
|
+
The axis.
|
|
69
|
+
|
|
70
|
+
Returns
|
|
71
|
+
-------
|
|
72
|
+
list[str]
|
|
73
|
+
One text per label.
|
|
74
|
+
|
|
75
|
+
Examples
|
|
76
|
+
--------
|
|
77
|
+
>>> from matplotlib.figure import Figure
|
|
78
|
+
>>> from numdaplot.plots.drawing.label_room import read_label_texts
|
|
79
|
+
>>> axes = Figure().add_subplot()
|
|
80
|
+
>>> axes.xaxis.set_ticks([0.0, 1.0], ["Paris", "Lyon"]) # doctest: +ELLIPSIS
|
|
81
|
+
[...]
|
|
82
|
+
>>> read_label_texts(axes.xaxis)
|
|
83
|
+
['Paris', 'Lyon']
|
|
84
|
+
"""
|
|
85
|
+
formatter = axis.get_major_formatter()
|
|
86
|
+
if isinstance(formatter, FixedFormatter):
|
|
87
|
+
fixed_texts = list(formatter.seq)
|
|
88
|
+
return fixed_texts
|
|
89
|
+
|
|
90
|
+
labels = axis.get_ticklabels()
|
|
91
|
+
label_texts = [label.get_text() for label in labels]
|
|
92
|
+
|
|
93
|
+
return label_texts
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def find_current_length(axis: Axis, on_vertical_axis: bool) -> float:
|
|
97
|
+
"""
|
|
98
|
+
Return the current length of the axes along an axis.
|
|
99
|
+
|
|
100
|
+
The axes do not have their final size yet: the layout will make them a little longer.
|
|
101
|
+
|
|
102
|
+
.. versionadded:: 0.1.0
|
|
103
|
+
|
|
104
|
+
Parameters
|
|
105
|
+
----------
|
|
106
|
+
axis
|
|
107
|
+
The axis.
|
|
108
|
+
on_vertical_axis
|
|
109
|
+
True for the vertical axis.
|
|
110
|
+
|
|
111
|
+
Returns
|
|
112
|
+
-------
|
|
113
|
+
float
|
|
114
|
+
The length, in pixels.
|
|
115
|
+
|
|
116
|
+
Examples
|
|
117
|
+
--------
|
|
118
|
+
>>> from matplotlib.figure import Figure
|
|
119
|
+
>>> from numdaplot.plots.drawing.label_room import find_current_length
|
|
120
|
+
>>> axes = Figure(figsize=(6.4, 4.8), dpi=100).add_subplot()
|
|
121
|
+
>>> round(find_current_length(axes.xaxis, False), 1)
|
|
122
|
+
496.0
|
|
123
|
+
"""
|
|
124
|
+
axes_box = axis.axes.get_window_extent()
|
|
125
|
+
axes_length = axes_box.height if on_vertical_axis else axes_box.width
|
|
126
|
+
|
|
127
|
+
return float(axes_length)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def estimate_final_length(axis: Axis, on_vertical_axis: bool) -> float:
|
|
131
|
+
"""
|
|
132
|
+
Return the length the axes will have along an axis, once the layout has given them their room.
|
|
133
|
+
|
|
134
|
+
.. versionadded:: 0.1.0
|
|
135
|
+
|
|
136
|
+
Parameters
|
|
137
|
+
----------
|
|
138
|
+
axis
|
|
139
|
+
The axis.
|
|
140
|
+
on_vertical_axis
|
|
141
|
+
True for the vertical axis.
|
|
142
|
+
|
|
143
|
+
Returns
|
|
144
|
+
-------
|
|
145
|
+
float
|
|
146
|
+
The size of the figure or subfigure less a usual margin, and at least the current length.
|
|
147
|
+
|
|
148
|
+
Examples
|
|
149
|
+
--------
|
|
150
|
+
>>> from matplotlib.figure import Figure
|
|
151
|
+
>>> from numdaplot.plots.drawing.label_room import estimate_final_length
|
|
152
|
+
>>> axes = Figure(figsize=(6.4, 4.8), dpi=100).add_subplot()
|
|
153
|
+
>>> estimate_final_length(axes.xaxis, False)
|
|
154
|
+
580.0
|
|
155
|
+
"""
|
|
156
|
+
current_length = find_current_length(axis, on_vertical_axis)
|
|
157
|
+
container = cast(Figure | SubFigure, axis.axes.get_figure())
|
|
158
|
+
container_length = container.bbox.width
|
|
159
|
+
if on_vertical_axis:
|
|
160
|
+
container_length = container.bbox.height
|
|
161
|
+
|
|
162
|
+
free_length = container_length - LAYOUT_MARGIN_PIXELS
|
|
163
|
+
final_length = max(free_length, current_length)
|
|
164
|
+
|
|
165
|
+
return float(final_length)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def find_tick_room(axis: Axis, on_vertical_axis: bool, axes_length: float) -> float:
|
|
169
|
+
"""
|
|
170
|
+
Return the pixels between the closest ticks of an axis.
|
|
171
|
+
|
|
172
|
+
.. versionadded:: 0.1.0
|
|
173
|
+
|
|
174
|
+
Parameters
|
|
175
|
+
----------
|
|
176
|
+
axis
|
|
177
|
+
The axis, with at least two ticks.
|
|
178
|
+
on_vertical_axis
|
|
179
|
+
True for the vertical axis.
|
|
180
|
+
axes_length
|
|
181
|
+
The length of the axes along this axis, in pixels.
|
|
182
|
+
|
|
183
|
+
Returns
|
|
184
|
+
-------
|
|
185
|
+
float
|
|
186
|
+
The room, in pixels.
|
|
187
|
+
|
|
188
|
+
Examples
|
|
189
|
+
--------
|
|
190
|
+
>>> from matplotlib.figure import Figure
|
|
191
|
+
>>> from numdaplot.plots.drawing.label_room import find_tick_room
|
|
192
|
+
>>> axes = Figure().add_subplot()
|
|
193
|
+
>>> axes.set_xlim(0.0, 10.0)
|
|
194
|
+
(0.0, 10.0)
|
|
195
|
+
>>> axes.xaxis.set_ticks([0.0, 1.0, 3.0], ["a", "b", "c"]) # doctest: +ELLIPSIS
|
|
196
|
+
[...]
|
|
197
|
+
>>> find_tick_room(axes.xaxis, False, 500.0)
|
|
198
|
+
50.0
|
|
199
|
+
"""
|
|
200
|
+
view_start, view_stop = axis.axes.get_xbound()
|
|
201
|
+
if on_vertical_axis:
|
|
202
|
+
view_start, view_stop = axis.axes.get_ybound()
|
|
203
|
+
|
|
204
|
+
pixels_per_unit = axes_length / (view_stop - view_start)
|
|
205
|
+
ticks = find_tick_locations(axis)
|
|
206
|
+
sorted_ticks = numpy.sort(ticks)
|
|
207
|
+
tick_gaps = numpy.diff(sorted_ticks)
|
|
208
|
+
smallest_tick_gap = tick_gaps.min()
|
|
209
|
+
room = smallest_tick_gap * pixels_per_unit
|
|
210
|
+
|
|
211
|
+
return float(room)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def find_font_pixels(axis: Axis) -> float:
|
|
215
|
+
"""
|
|
216
|
+
Return the font size of the labels of an axis, in pixels.
|
|
217
|
+
|
|
218
|
+
.. versionadded:: 0.1.0
|
|
219
|
+
|
|
220
|
+
Parameters
|
|
221
|
+
----------
|
|
222
|
+
axis
|
|
223
|
+
The axis, with at least one tick.
|
|
224
|
+
|
|
225
|
+
Returns
|
|
226
|
+
-------
|
|
227
|
+
float
|
|
228
|
+
The font size.
|
|
229
|
+
|
|
230
|
+
Examples
|
|
231
|
+
--------
|
|
232
|
+
>>> from matplotlib.figure import Figure
|
|
233
|
+
>>> from numdaplot.plots.drawing.label_room import find_font_pixels
|
|
234
|
+
>>> axes = Figure(dpi=72).add_subplot()
|
|
235
|
+
>>> axes.tick_params(labelsize=12.0)
|
|
236
|
+
>>> find_font_pixels(axes.xaxis)
|
|
237
|
+
12.0
|
|
238
|
+
"""
|
|
239
|
+
first_tick = axis.get_major_ticks(1)[0]
|
|
240
|
+
font_size = cast(float, first_tick.label1.get_fontsize())
|
|
241
|
+
figure = cast(Figure, axis.axes.get_figure(root=True))
|
|
242
|
+
font_pixels = font_size * figure.dpi / POINTS_PER_INCH
|
|
243
|
+
|
|
244
|
+
return font_pixels
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def find_widest_label(axis: Axis) -> float:
|
|
248
|
+
"""
|
|
249
|
+
Return the width of the widest label of an axis, as written horizontally.
|
|
250
|
+
|
|
251
|
+
Measuring a text is slow, so only the labels with the most characters are measured, the widest one being among
|
|
252
|
+
them in practice.
|
|
253
|
+
|
|
254
|
+
.. versionadded:: 0.1.0
|
|
255
|
+
|
|
256
|
+
Parameters
|
|
257
|
+
----------
|
|
258
|
+
axis
|
|
259
|
+
The axis, with labels that are not rotated yet.
|
|
260
|
+
|
|
261
|
+
Returns
|
|
262
|
+
-------
|
|
263
|
+
float
|
|
264
|
+
The width, in pixels.
|
|
265
|
+
|
|
266
|
+
Examples
|
|
267
|
+
--------
|
|
268
|
+
>>> from matplotlib.figure import Figure
|
|
269
|
+
>>> from numdaplot.plots.drawing.label_room import find_widest_label
|
|
270
|
+
>>> axes = Figure().add_subplot()
|
|
271
|
+
>>> axes.xaxis.set_ticks([0.0, 1.0], ["a", "a long label"]) # doctest: +ELLIPSIS
|
|
272
|
+
[...]
|
|
273
|
+
>>> bool(find_widest_label(axes.xaxis) > 50.0)
|
|
274
|
+
True
|
|
275
|
+
"""
|
|
276
|
+
label_texts = read_label_texts(axis)
|
|
277
|
+
measured_texts = heapq.nlargest(MEASURED_LABEL_COUNT, label_texts, key=len)
|
|
278
|
+
measuring_label = axis.get_major_ticks(1)[0].label1
|
|
279
|
+
first_text = measuring_label.get_text()
|
|
280
|
+
label_widths = list[float]()
|
|
281
|
+
|
|
282
|
+
for measured_text in measured_texts:
|
|
283
|
+
measuring_label.set_text(measured_text)
|
|
284
|
+
label_box = measuring_label.get_window_extent()
|
|
285
|
+
label_widths.append(label_box.width)
|
|
286
|
+
|
|
287
|
+
measuring_label.set_text(first_text)
|
|
288
|
+
widest_label = max(label_widths)
|
|
289
|
+
|
|
290
|
+
return widest_label
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def find_needed_room(axis: Axis, on_vertical_axis: bool, rotation: float) -> float:
|
|
294
|
+
"""
|
|
295
|
+
Return the pixels two neighbor labels of an axis need between their ticks.
|
|
296
|
+
|
|
297
|
+
Labels along the axis need their width. Slanted labels sit side by side, so they need their font size divided
|
|
298
|
+
by the sine of the angle with the axis, unless the whole label fits in less.
|
|
299
|
+
|
|
300
|
+
.. versionadded:: 0.1.0
|
|
301
|
+
|
|
302
|
+
Parameters
|
|
303
|
+
----------
|
|
304
|
+
axis
|
|
305
|
+
The axis, with labels that are not rotated yet.
|
|
306
|
+
on_vertical_axis
|
|
307
|
+
True for the vertical axis.
|
|
308
|
+
rotation
|
|
309
|
+
The angle of the labels in degrees, from the horizontal.
|
|
310
|
+
|
|
311
|
+
Returns
|
|
312
|
+
-------
|
|
313
|
+
float
|
|
314
|
+
The room needed, in pixels.
|
|
315
|
+
|
|
316
|
+
Examples
|
|
317
|
+
--------
|
|
318
|
+
>>> from matplotlib.figure import Figure
|
|
319
|
+
>>> from numdaplot.plots.drawing.label_room import find_needed_room
|
|
320
|
+
>>> axes = Figure(dpi=72).add_subplot()
|
|
321
|
+
>>> axes.tick_params(labelsize=10.0)
|
|
322
|
+
>>> axes.yaxis.set_ticks([0.0, 1.0], ["Paris", "Lyon"]) # doctest: +ELLIPSIS
|
|
323
|
+
[...]
|
|
324
|
+
>>> find_needed_room(axes.yaxis, True, 0.0)
|
|
325
|
+
10.0
|
|
326
|
+
"""
|
|
327
|
+
font_pixels = find_font_pixels(axis)
|
|
328
|
+
widest_label = find_widest_label(axis)
|
|
329
|
+
angle_with_axis = abs(rotation)
|
|
330
|
+
if on_vertical_axis:
|
|
331
|
+
angle_with_axis = RIGHT_ANGLE - angle_with_axis
|
|
332
|
+
|
|
333
|
+
if angle_with_axis == 0:
|
|
334
|
+
along_axis_room = widest_label + font_pixels * LABEL_GAP_RATIO
|
|
335
|
+
return along_axis_room
|
|
336
|
+
|
|
337
|
+
angle_radians = math.radians(angle_with_axis)
|
|
338
|
+
sine = math.sin(angle_radians)
|
|
339
|
+
cosine = math.cos(angle_radians)
|
|
340
|
+
side_by_side_room = font_pixels / sine
|
|
341
|
+
whole_label_room = widest_label * cosine + font_pixels * sine
|
|
342
|
+
needed_room = min(side_by_side_room, whole_label_room)
|
|
343
|
+
|
|
344
|
+
return needed_room
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Choice of the labels of an axis that fit, the others being left out so that they stay readable.
|
|
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
|
+
import math
|
|
11
|
+
import warnings
|
|
12
|
+
|
|
13
|
+
import numpy
|
|
14
|
+
from matplotlib.axis import Axis
|
|
15
|
+
from matplotlib.ticker import FixedLocator
|
|
16
|
+
|
|
17
|
+
from numdaplot.arrays.operations.float_errors import INTERNAL_FILES
|
|
18
|
+
from numdaplot.errors.readability_warning import ReadabilityWarning
|
|
19
|
+
from numdaplot.plots.drawing.label_room import (
|
|
20
|
+
estimate_final_length,
|
|
21
|
+
find_needed_room,
|
|
22
|
+
find_tick_locations,
|
|
23
|
+
find_tick_room,
|
|
24
|
+
read_label_texts,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
MINIMUM_TICKS = 2
|
|
28
|
+
EVERY_LABEL = 1
|
|
29
|
+
MINUS_SIGN = "\N{MINUS SIGN}"
|
|
30
|
+
HYPHEN_MINUS = "-"
|
|
31
|
+
WIDER_SIZE = "wider"
|
|
32
|
+
TALLER_SIZE = "taller"
|
|
33
|
+
HIDDEN_LABELS_MESSAGE = (
|
|
34
|
+
"The chart shows {shown_count} of its {label_count} labels so that they stay readable. "
|
|
35
|
+
"Give a {size_word} ndp.Size to show more of them."
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def find_label_step(axis: Axis, on_vertical_axis: bool, rotation: float) -> int:
|
|
40
|
+
"""
|
|
41
|
+
Return how often a label of an axis can be shown: 1 for each one, 3 for one out of three.
|
|
42
|
+
|
|
43
|
+
.. versionadded:: 0.1.0
|
|
44
|
+
|
|
45
|
+
Parameters
|
|
46
|
+
----------
|
|
47
|
+
axis
|
|
48
|
+
The axis, with labels that are not rotated yet.
|
|
49
|
+
on_vertical_axis
|
|
50
|
+
True for the vertical axis.
|
|
51
|
+
rotation
|
|
52
|
+
The angle the labels will take, in degrees.
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
-------
|
|
56
|
+
int
|
|
57
|
+
The step, 1 when the ticks are not fixed on each value, as matplotlib then chooses labels that fit.
|
|
58
|
+
|
|
59
|
+
Examples
|
|
60
|
+
--------
|
|
61
|
+
>>> from matplotlib.figure import Figure
|
|
62
|
+
>>> from numdaplot.plots.drawing.label_thinning import find_label_step
|
|
63
|
+
>>> axes = Figure(figsize=(6.4, 4.8), dpi=100).add_subplot()
|
|
64
|
+
>>> ticks = [float(tick) for tick in range(60)]
|
|
65
|
+
>>> axes.xaxis.set_ticks(ticks, [str(tick) for tick in ticks]) # doctest: +ELLIPSIS
|
|
66
|
+
[...]
|
|
67
|
+
>>> find_label_step(axes.xaxis, False, 45.0)
|
|
68
|
+
2
|
|
69
|
+
"""
|
|
70
|
+
locator = axis.get_major_locator()
|
|
71
|
+
if not isinstance(locator, FixedLocator):
|
|
72
|
+
return EVERY_LABEL
|
|
73
|
+
|
|
74
|
+
tick_locations = find_tick_locations(axis)
|
|
75
|
+
tick_count = len(tick_locations)
|
|
76
|
+
if tick_count < MINIMUM_TICKS:
|
|
77
|
+
return EVERY_LABEL
|
|
78
|
+
|
|
79
|
+
final_length = estimate_final_length(axis, on_vertical_axis)
|
|
80
|
+
room = find_tick_room(axis, on_vertical_axis, final_length)
|
|
81
|
+
if room <= 0:
|
|
82
|
+
return EVERY_LABEL
|
|
83
|
+
|
|
84
|
+
needed_room = find_needed_room(axis, on_vertical_axis, rotation)
|
|
85
|
+
room_ratio = needed_room / room
|
|
86
|
+
label_step = math.ceil(room_ratio)
|
|
87
|
+
|
|
88
|
+
return label_step
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def is_ordered_text(text: str) -> bool:
|
|
92
|
+
"""
|
|
93
|
+
Return whether a label is a number or a date, which a reader can find from its neighbors.
|
|
94
|
+
|
|
95
|
+
.. versionadded:: 0.1.0
|
|
96
|
+
|
|
97
|
+
Parameters
|
|
98
|
+
----------
|
|
99
|
+
text
|
|
100
|
+
The text of a label.
|
|
101
|
+
|
|
102
|
+
Returns
|
|
103
|
+
-------
|
|
104
|
+
bool
|
|
105
|
+
True for a number, a date, a datetime or an empty label, False for another text.
|
|
106
|
+
|
|
107
|
+
Examples
|
|
108
|
+
--------
|
|
109
|
+
>>> from numdaplot.plots.drawing.label_thinning import is_ordered_text
|
|
110
|
+
>>> is_ordered_text("2025"), is_ordered_text("2026-01-31"), is_ordered_text("Paris")
|
|
111
|
+
(True, True, False)
|
|
112
|
+
"""
|
|
113
|
+
if text == "":
|
|
114
|
+
return True
|
|
115
|
+
|
|
116
|
+
python_text = text.replace(MINUS_SIGN, HYPHEN_MINUS)
|
|
117
|
+
try:
|
|
118
|
+
float(python_text)
|
|
119
|
+
except ValueError:
|
|
120
|
+
pass
|
|
121
|
+
else:
|
|
122
|
+
return True
|
|
123
|
+
|
|
124
|
+
try:
|
|
125
|
+
numpy.datetime64(python_text)
|
|
126
|
+
except ValueError:
|
|
127
|
+
return False
|
|
128
|
+
|
|
129
|
+
return True
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def warn_hidden_labels(label_texts: list[str], shown_count: int, on_vertical_axis: bool) -> None:
|
|
133
|
+
"""
|
|
134
|
+
Warn that labels naming the values of a chart are left out, numbers and dates being found from their neighbors.
|
|
135
|
+
|
|
136
|
+
.. versionadded:: 0.1.0
|
|
137
|
+
|
|
138
|
+
Parameters
|
|
139
|
+
----------
|
|
140
|
+
label_texts
|
|
141
|
+
Every label of the axis.
|
|
142
|
+
shown_count
|
|
143
|
+
The number of labels kept.
|
|
144
|
+
on_vertical_axis
|
|
145
|
+
True for the vertical axis, which needs a taller size to show more labels.
|
|
146
|
+
|
|
147
|
+
Warns
|
|
148
|
+
-----
|
|
149
|
+
ReadabilityWarning
|
|
150
|
+
When a left out label may be a text.
|
|
151
|
+
|
|
152
|
+
Examples
|
|
153
|
+
--------
|
|
154
|
+
>>> import warnings
|
|
155
|
+
>>> from numdaplot.plots.drawing.label_thinning import warn_hidden_labels
|
|
156
|
+
>>> with warnings.catch_warnings(record=True) as caught_warnings:
|
|
157
|
+
... warnings.simplefilter("always")
|
|
158
|
+
... warn_hidden_labels(["Paris", "Lyon", "Nice"], 2, False)
|
|
159
|
+
>>> print(caught_warnings[0].message)
|
|
160
|
+
The chart shows 2 of its 3 labels so that they stay readable. Give a wider ndp.Size to show more of them.
|
|
161
|
+
"""
|
|
162
|
+
ordered_labels = (is_ordered_text(label_text) for label_text in label_texts)
|
|
163
|
+
if all(ordered_labels):
|
|
164
|
+
return
|
|
165
|
+
|
|
166
|
+
label_count = len(label_texts)
|
|
167
|
+
size_word = TALLER_SIZE if on_vertical_axis else WIDER_SIZE
|
|
168
|
+
message = HIDDEN_LABELS_MESSAGE.format(shown_count=shown_count, label_count=label_count, size_word=size_word)
|
|
169
|
+
warnings.warn(message, ReadabilityWarning, skip_file_prefixes=INTERNAL_FILES)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def thin_labels(axis: Axis, on_vertical_axis: bool, rotation: float) -> None:
|
|
173
|
+
"""
|
|
174
|
+
Keep one label out of as many as needed for the labels of an axis to stay readable, from the first one.
|
|
175
|
+
|
|
176
|
+
The tick marks of the labels left out are removed too, so each mark left has its label.
|
|
177
|
+
|
|
178
|
+
.. versionadded:: 0.1.0
|
|
179
|
+
|
|
180
|
+
Parameters
|
|
181
|
+
----------
|
|
182
|
+
axis
|
|
183
|
+
The axis, with labels that are not rotated yet.
|
|
184
|
+
on_vertical_axis
|
|
185
|
+
True for the vertical axis.
|
|
186
|
+
rotation
|
|
187
|
+
The angle the labels will take, in degrees.
|
|
188
|
+
|
|
189
|
+
Warns
|
|
190
|
+
-----
|
|
191
|
+
ReadabilityWarning
|
|
192
|
+
When a left out label may be a text.
|
|
193
|
+
|
|
194
|
+
Examples
|
|
195
|
+
--------
|
|
196
|
+
>>> from matplotlib.figure import Figure
|
|
197
|
+
>>> from numdaplot.plots.drawing.label_thinning import thin_labels
|
|
198
|
+
>>> axes = Figure(figsize=(6.4, 4.8), dpi=100).add_subplot()
|
|
199
|
+
>>> ticks = [float(tick) for tick in range(60)]
|
|
200
|
+
>>> axes.xaxis.set_ticks(ticks, [str(int(tick)) for tick in ticks]) # doctest: +ELLIPSIS
|
|
201
|
+
[...]
|
|
202
|
+
>>> thin_labels(axes.xaxis, False, 45.0)
|
|
203
|
+
>>> [label.get_text() for label in axes.get_xticklabels()][:3]
|
|
204
|
+
['0', '2', '4']
|
|
205
|
+
"""
|
|
206
|
+
label_step = find_label_step(axis, on_vertical_axis, rotation)
|
|
207
|
+
if label_step == EVERY_LABEL:
|
|
208
|
+
return
|
|
209
|
+
|
|
210
|
+
label_texts = read_label_texts(axis)
|
|
211
|
+
ticks = find_tick_locations(axis)
|
|
212
|
+
kept_ticks = ticks[::label_step]
|
|
213
|
+
kept_texts = label_texts[::label_step]
|
|
214
|
+
axis.set_ticks(kept_ticks, kept_texts)
|
|
215
|
+
shown_count = len(kept_texts)
|
|
216
|
+
warn_hidden_labels(label_texts, shown_count, on_vertical_axis)
|