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,59 @@
|
|
|
1
|
+
"""
|
|
2
|
+
How a Conversion reads numbers as booleans.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from enum import Enum, auto
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class BooleanRule(Enum):
|
|
11
|
+
"""
|
|
12
|
+
How a ``Conversion`` of a number column to ``BOOL`` reads each number.
|
|
13
|
+
|
|
14
|
+
.. versionadded:: 0.1.0
|
|
15
|
+
|
|
16
|
+
Examples
|
|
17
|
+
--------
|
|
18
|
+
>>> import numdaplot as ndp
|
|
19
|
+
>>> visits = ndp.Table.from_arrays({"visits": ndp.Array.from_list([0, 3])})
|
|
20
|
+
>>> rule = ndp.BooleanRule.NONZERO_TRUE
|
|
21
|
+
>>> visits.convert(ndp.Conversion(column="visits", dtype=ndp.Type.BOOL, booleans=rule))
|
|
22
|
+
visits
|
|
23
|
+
BOOL
|
|
24
|
+
0 False
|
|
25
|
+
1 True
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
ZERO_ONE = auto()
|
|
29
|
+
"""
|
|
30
|
+
0 gives ``False`` and 1 gives ``True``; any other number raises ``ValueConversionError``. Used when ``booleans``
|
|
31
|
+
is omitted.
|
|
32
|
+
|
|
33
|
+
Examples
|
|
34
|
+
--------
|
|
35
|
+
>>> import numdaplot as ndp
|
|
36
|
+
>>> severe = ndp.Table.from_arrays({"severe": ndp.Array.from_list([1, 0])})
|
|
37
|
+
>>> severe.convert(ndp.Conversion(column="severe", dtype=ndp.Type.BOOL, booleans=ndp.BooleanRule.ZERO_ONE))
|
|
38
|
+
severe
|
|
39
|
+
BOOL
|
|
40
|
+
0 True
|
|
41
|
+
1 False
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
NONZERO_TRUE = auto()
|
|
45
|
+
"""
|
|
46
|
+
0 gives ``False`` and any other number gives ``True``, as in Python.
|
|
47
|
+
|
|
48
|
+
Examples
|
|
49
|
+
--------
|
|
50
|
+
>>> import numdaplot as ndp
|
|
51
|
+
>>> visits = ndp.Table.from_arrays({"visits": ndp.Array.from_list([0, 3, -1])})
|
|
52
|
+
>>> rule = ndp.BooleanRule.NONZERO_TRUE
|
|
53
|
+
>>> visits.convert(ndp.Conversion(column="visits", dtype=ndp.Type.BOOL, booleans=rule))
|
|
54
|
+
visits
|
|
55
|
+
BOOL
|
|
56
|
+
0 False
|
|
57
|
+
1 True
|
|
58
|
+
2 True
|
|
59
|
+
"""
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Whether the first or the last bracket of Brackets has a limit.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from enum import Enum, auto
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class BracketEnd(Enum):
|
|
11
|
+
"""
|
|
12
|
+
Whether the first or the last bracket of ``Brackets`` stops at a limit or holds every value beyond it.
|
|
13
|
+
|
|
14
|
+
.. versionadded:: 0.1.0
|
|
15
|
+
|
|
16
|
+
Examples
|
|
17
|
+
--------
|
|
18
|
+
>>> import numdaplot as ndp
|
|
19
|
+
>>> ages = ndp.Table.from_arrays({"age": ndp.Array.from_list([4, 30, 92])})
|
|
20
|
+
>>> brackets = ndp.Brackets(limits=[0, 18, 65], last=ndp.BracketEnd.OPEN)
|
|
21
|
+
>>> ages.convert(ndp.Conversion(column="age", dtype=ndp.Type.CATEGORY, format=brackets)).column("age").to_list()
|
|
22
|
+
['0 to 17', '18 to 64', '65 or more']
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
CLOSED = auto()
|
|
26
|
+
"""
|
|
27
|
+
The bracket stops at its limit. Default value.
|
|
28
|
+
|
|
29
|
+
Examples
|
|
30
|
+
--------
|
|
31
|
+
>>> import numdaplot as ndp
|
|
32
|
+
>>> ages = ndp.Table.from_arrays({"age": ndp.Array.from_list([4, 30])})
|
|
33
|
+
>>> brackets = ndp.Brackets(limits=[0, 18, 65], last=ndp.BracketEnd.CLOSED)
|
|
34
|
+
>>> ages.convert(ndp.Conversion(column="age", dtype=ndp.Type.CATEGORY, format=brackets)).column("age").to_list()
|
|
35
|
+
['0 to 17', '18 to 64']
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
OPEN = auto()
|
|
39
|
+
"""
|
|
40
|
+
The bracket holds every value beyond the limit: below the first one, or above the last one.
|
|
41
|
+
|
|
42
|
+
Examples
|
|
43
|
+
--------
|
|
44
|
+
>>> import numdaplot as ndp
|
|
45
|
+
>>> temperatures = ndp.Table.from_arrays({"celsius": ndp.Array.from_list([-3.5, 12.0])})
|
|
46
|
+
>>> brackets = ndp.Brackets(limits=[0, 15], first=ndp.BracketEnd.OPEN)
|
|
47
|
+
>>> conversion = ndp.Conversion(column="celsius", dtype=ndp.Type.CATEGORY, format=brackets)
|
|
48
|
+
>>> temperatures.convert(conversion).column("celsius").to_list()
|
|
49
|
+
['under 0', '0 to under 15']
|
|
50
|
+
"""
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Names of brackets written from the values they hold.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import math
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from typing import cast
|
|
10
|
+
|
|
11
|
+
from numdaplot.errors.invalid_limits_error import InvalidLimitsError
|
|
12
|
+
from numdaplot.rules.bounds import Bounds
|
|
13
|
+
from numdaplot.tables.columns.bracket_end import BracketEnd
|
|
14
|
+
from numdaplot.tables.columns.brackets import Brackets
|
|
15
|
+
|
|
16
|
+
CLOSED_INTEGERS = "{low} to {high}"
|
|
17
|
+
INTEGERS_OR_MORE = "{low} or more"
|
|
18
|
+
INTEGERS_OR_LESS = "{high} or less"
|
|
19
|
+
LOW_DECIMALS = "{low} to under {high}"
|
|
20
|
+
HIGH_DECIMALS = "over {low} to {high}"
|
|
21
|
+
DECIMALS_OR_MORE = "{low} or more"
|
|
22
|
+
OVER_DECIMALS = "over {low}"
|
|
23
|
+
UNDER_DECIMALS = "under {high}"
|
|
24
|
+
DECIMALS_OR_LESS = "{high} or less"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(frozen=True)
|
|
28
|
+
class Bracket:
|
|
29
|
+
"""
|
|
30
|
+
One bracket: its low and its high limit, None on an open side.
|
|
31
|
+
|
|
32
|
+
.. versionadded:: 0.1.0
|
|
33
|
+
|
|
34
|
+
Parameters
|
|
35
|
+
----------
|
|
36
|
+
low
|
|
37
|
+
The low limit, None for an open first bracket.
|
|
38
|
+
high
|
|
39
|
+
The high limit, None for an open last bracket.
|
|
40
|
+
|
|
41
|
+
Examples
|
|
42
|
+
--------
|
|
43
|
+
>>> from numdaplot.tables.columns.bracket_names import Bracket
|
|
44
|
+
>>> Bracket(0, 10).high
|
|
45
|
+
10
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
low: int | float | None
|
|
49
|
+
high: int | float | None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def list_brackets(brackets: Brackets) -> list[Bracket]:
|
|
53
|
+
"""
|
|
54
|
+
Return each bracket in order, open ones included.
|
|
55
|
+
|
|
56
|
+
.. versionadded:: 0.1.0
|
|
57
|
+
|
|
58
|
+
Parameters
|
|
59
|
+
----------
|
|
60
|
+
brackets
|
|
61
|
+
The limits and the open ends.
|
|
62
|
+
|
|
63
|
+
Returns
|
|
64
|
+
-------
|
|
65
|
+
list[Bracket]
|
|
66
|
+
One bracket between two limits, an open one before the first limit or after the last one when asked.
|
|
67
|
+
|
|
68
|
+
Examples
|
|
69
|
+
--------
|
|
70
|
+
>>> import numdaplot as ndp
|
|
71
|
+
>>> from numdaplot.tables.columns.bracket_names import list_brackets
|
|
72
|
+
>>> list_brackets(ndp.Brackets(limits=[0, 10], last=ndp.BracketEnd.OPEN))
|
|
73
|
+
[Bracket(low=0, high=10), Bracket(low=10, high=None)]
|
|
74
|
+
"""
|
|
75
|
+
bracket_list = list[Bracket]()
|
|
76
|
+
limits = brackets.limits
|
|
77
|
+
if brackets.first == BracketEnd.OPEN:
|
|
78
|
+
first_limit = limits[0]
|
|
79
|
+
open_first = Bracket(None, first_limit)
|
|
80
|
+
bracket_list.append(open_first)
|
|
81
|
+
|
|
82
|
+
for low, high in zip(limits, limits[1:], strict=False):
|
|
83
|
+
closed_bracket = Bracket(low, high)
|
|
84
|
+
bracket_list.append(closed_bracket)
|
|
85
|
+
|
|
86
|
+
if brackets.last == BracketEnd.OPEN:
|
|
87
|
+
last_limit = limits[-1]
|
|
88
|
+
open_last = Bracket(last_limit, None)
|
|
89
|
+
bracket_list.append(open_last)
|
|
90
|
+
|
|
91
|
+
return bracket_list
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def write_bracket_names(brackets: Brackets, holds_integers: bool) -> list[str]:
|
|
95
|
+
"""
|
|
96
|
+
Return the name of each bracket: the given labels, or the values each bracket holds.
|
|
97
|
+
|
|
98
|
+
.. versionadded:: 0.1.0
|
|
99
|
+
|
|
100
|
+
Parameters
|
|
101
|
+
----------
|
|
102
|
+
brackets
|
|
103
|
+
The limits, the bounds, the open ends and the labels.
|
|
104
|
+
holds_integers
|
|
105
|
+
Whether the column holds integers, whose names give the first and the last integer of each bracket.
|
|
106
|
+
|
|
107
|
+
Returns
|
|
108
|
+
-------
|
|
109
|
+
list[str]
|
|
110
|
+
One name per bracket, in order.
|
|
111
|
+
|
|
112
|
+
Raises
|
|
113
|
+
------
|
|
114
|
+
InvalidLimitsError
|
|
115
|
+
When a bracket between two limits holds no integer of a column of integers.
|
|
116
|
+
|
|
117
|
+
Examples
|
|
118
|
+
--------
|
|
119
|
+
>>> import numdaplot as ndp
|
|
120
|
+
>>> from numdaplot.tables.columns.bracket_names import write_bracket_names
|
|
121
|
+
>>> write_bracket_names(ndp.Brackets(limits=[0, 10, 20], last=ndp.BracketEnd.OPEN), True)
|
|
122
|
+
['0 to 9', '10 to 19', '20 or more']
|
|
123
|
+
>>> write_bracket_names(ndp.Brackets(limits=[0, 10], bounds=ndp.Bounds.HIGH_ONLY), False)
|
|
124
|
+
['over 0 to 10']
|
|
125
|
+
"""
|
|
126
|
+
names = list[str]()
|
|
127
|
+
for bracket in list_brackets(brackets):
|
|
128
|
+
if holds_integers:
|
|
129
|
+
name = write_integer_name(bracket, brackets)
|
|
130
|
+
else:
|
|
131
|
+
name = write_decimal_name(bracket, brackets.bounds)
|
|
132
|
+
|
|
133
|
+
names.append(name)
|
|
134
|
+
|
|
135
|
+
if brackets.labels is not None:
|
|
136
|
+
return brackets.labels
|
|
137
|
+
|
|
138
|
+
return names
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def write_integer_name(bracket: Bracket, brackets: Brackets) -> str:
|
|
142
|
+
"""
|
|
143
|
+
Return the name of a bracket of integers: its first and its last integer.
|
|
144
|
+
|
|
145
|
+
.. versionadded:: 0.1.0
|
|
146
|
+
|
|
147
|
+
Parameters
|
|
148
|
+
----------
|
|
149
|
+
bracket
|
|
150
|
+
The limits of the bracket.
|
|
151
|
+
brackets
|
|
152
|
+
The bounds, and the limits named by the error.
|
|
153
|
+
|
|
154
|
+
Returns
|
|
155
|
+
-------
|
|
156
|
+
str
|
|
157
|
+
``0 to 9``, ``5`` for a single integer, ``80 or more`` or ``-1 or less`` for an open bracket.
|
|
158
|
+
|
|
159
|
+
Raises
|
|
160
|
+
------
|
|
161
|
+
InvalidLimitsError
|
|
162
|
+
When the bracket holds no integer.
|
|
163
|
+
|
|
164
|
+
Examples
|
|
165
|
+
--------
|
|
166
|
+
>>> import numdaplot as ndp
|
|
167
|
+
>>> from numdaplot.tables.columns.bracket_names import Bracket, write_integer_name
|
|
168
|
+
>>> write_integer_name(Bracket(0.5, 10), ndp.Brackets(limits=[0.5, 10]))
|
|
169
|
+
'1 to 9'
|
|
170
|
+
"""
|
|
171
|
+
if bracket.low is None:
|
|
172
|
+
# A bracket open on its low side always has a high limit, as Brackets needs a limit or an open end on each side.
|
|
173
|
+
high_limit = cast(int | float, bracket.high)
|
|
174
|
+
last_held = find_last_integer(high_limit, brackets.bounds)
|
|
175
|
+
less_name = INTEGERS_OR_LESS.format(high=last_held)
|
|
176
|
+
return less_name
|
|
177
|
+
|
|
178
|
+
first_integer = find_first_integer(bracket.low, brackets.bounds)
|
|
179
|
+
if bracket.high is None:
|
|
180
|
+
more_name = INTEGERS_OR_MORE.format(low=first_integer)
|
|
181
|
+
return more_name
|
|
182
|
+
|
|
183
|
+
last_integer = find_last_integer(bracket.high, brackets.bounds)
|
|
184
|
+
if first_integer > last_integer:
|
|
185
|
+
empty_bracket = [bracket.low, bracket.high]
|
|
186
|
+
raise InvalidLimitsError(brackets.limits, empty_bracket)
|
|
187
|
+
|
|
188
|
+
if first_integer == last_integer:
|
|
189
|
+
single_name = str(first_integer)
|
|
190
|
+
return single_name
|
|
191
|
+
|
|
192
|
+
closed_name = CLOSED_INTEGERS.format(low=first_integer, high=last_integer)
|
|
193
|
+
|
|
194
|
+
return closed_name
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def find_first_integer(low: int | float, bounds: Bounds) -> int:
|
|
198
|
+
"""
|
|
199
|
+
Return the smallest integer of a bracket from its low limit.
|
|
200
|
+
|
|
201
|
+
.. versionadded:: 0.1.0
|
|
202
|
+
|
|
203
|
+
Parameters
|
|
204
|
+
----------
|
|
205
|
+
low
|
|
206
|
+
The low limit.
|
|
207
|
+
bounds
|
|
208
|
+
``LOW_ONLY`` when the bracket holds its low limit, ``HIGH_ONLY`` otherwise.
|
|
209
|
+
|
|
210
|
+
Returns
|
|
211
|
+
-------
|
|
212
|
+
int
|
|
213
|
+
The low limit rounded up, plus one when the bracket does not hold it and it is a whole number.
|
|
214
|
+
|
|
215
|
+
Examples
|
|
216
|
+
--------
|
|
217
|
+
>>> import numdaplot as ndp
|
|
218
|
+
>>> from numdaplot.tables.columns.bracket_names import find_first_integer
|
|
219
|
+
>>> find_first_integer(10, ndp.Bounds.LOW_ONLY), find_first_integer(10, ndp.Bounds.HIGH_ONLY)
|
|
220
|
+
(10, 11)
|
|
221
|
+
"""
|
|
222
|
+
if bounds == Bounds.LOW_ONLY:
|
|
223
|
+
held_low = math.ceil(low)
|
|
224
|
+
return held_low
|
|
225
|
+
|
|
226
|
+
low_floor = math.floor(low)
|
|
227
|
+
first_integer = low_floor + 1
|
|
228
|
+
|
|
229
|
+
return first_integer
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def find_last_integer(high: int | float, bounds: Bounds) -> int:
|
|
233
|
+
"""
|
|
234
|
+
Return the largest integer of a bracket from its high limit.
|
|
235
|
+
|
|
236
|
+
.. versionadded:: 0.1.0
|
|
237
|
+
|
|
238
|
+
Parameters
|
|
239
|
+
----------
|
|
240
|
+
high
|
|
241
|
+
The high limit.
|
|
242
|
+
bounds
|
|
243
|
+
``HIGH_ONLY`` when the bracket holds its high limit, ``LOW_ONLY`` otherwise.
|
|
244
|
+
|
|
245
|
+
Returns
|
|
246
|
+
-------
|
|
247
|
+
int
|
|
248
|
+
The high limit rounded down, minus one when the bracket does not hold it and it is a whole number.
|
|
249
|
+
|
|
250
|
+
Examples
|
|
251
|
+
--------
|
|
252
|
+
>>> import numdaplot as ndp
|
|
253
|
+
>>> from numdaplot.tables.columns.bracket_names import find_last_integer
|
|
254
|
+
>>> find_last_integer(10, ndp.Bounds.LOW_ONLY), find_last_integer(10, ndp.Bounds.HIGH_ONLY)
|
|
255
|
+
(9, 10)
|
|
256
|
+
"""
|
|
257
|
+
if bounds == Bounds.HIGH_ONLY:
|
|
258
|
+
held_high = math.floor(high)
|
|
259
|
+
return held_high
|
|
260
|
+
|
|
261
|
+
high_ceiling = math.ceil(high)
|
|
262
|
+
last_integer = high_ceiling - 1
|
|
263
|
+
|
|
264
|
+
return last_integer
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def write_decimal_name(bracket: Bracket, bounds: Bounds) -> str:
|
|
268
|
+
"""
|
|
269
|
+
Return the name of a bracket of decimals, telling which limit it holds.
|
|
270
|
+
|
|
271
|
+
.. versionadded:: 0.1.0
|
|
272
|
+
|
|
273
|
+
Parameters
|
|
274
|
+
----------
|
|
275
|
+
bracket
|
|
276
|
+
The limits of the bracket.
|
|
277
|
+
bounds
|
|
278
|
+
``LOW_ONLY`` or ``HIGH_ONLY``.
|
|
279
|
+
|
|
280
|
+
Returns
|
|
281
|
+
-------
|
|
282
|
+
str
|
|
283
|
+
``0 to under 10`` or ``over 0 to 10``, and for an open bracket ``80 or more``, ``over 80``, ``under 0`` or
|
|
284
|
+
``0 or less``.
|
|
285
|
+
|
|
286
|
+
Examples
|
|
287
|
+
--------
|
|
288
|
+
>>> import numdaplot as ndp
|
|
289
|
+
>>> from numdaplot.tables.columns.bracket_names import Bracket, write_decimal_name
|
|
290
|
+
>>> write_decimal_name(Bracket(0.5, None), ndp.Bounds.HIGH_ONLY)
|
|
291
|
+
'over 0.5'
|
|
292
|
+
"""
|
|
293
|
+
low_text = write_limit(bracket.low)
|
|
294
|
+
high_text = write_limit(bracket.high)
|
|
295
|
+
holds_low = bounds == Bounds.LOW_ONLY
|
|
296
|
+
if bracket.low is None:
|
|
297
|
+
under_template = UNDER_DECIMALS if holds_low else DECIMALS_OR_LESS
|
|
298
|
+
under_name = under_template.format(high=high_text)
|
|
299
|
+
return under_name
|
|
300
|
+
|
|
301
|
+
if bracket.high is None:
|
|
302
|
+
over_template = DECIMALS_OR_MORE if holds_low else OVER_DECIMALS
|
|
303
|
+
over_name = over_template.format(low=low_text)
|
|
304
|
+
return over_name
|
|
305
|
+
|
|
306
|
+
closed_template = LOW_DECIMALS if holds_low else HIGH_DECIMALS
|
|
307
|
+
closed_name = closed_template.format(low=low_text, high=high_text)
|
|
308
|
+
|
|
309
|
+
return closed_name
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def write_limit(limit: int | float | None) -> str:
|
|
313
|
+
"""
|
|
314
|
+
Return a limit with the fewest digits that give it back, a whole number without decimals.
|
|
315
|
+
|
|
316
|
+
.. versionadded:: 0.1.0
|
|
317
|
+
|
|
318
|
+
Parameters
|
|
319
|
+
----------
|
|
320
|
+
limit
|
|
321
|
+
A limit, or None.
|
|
322
|
+
|
|
323
|
+
Returns
|
|
324
|
+
-------
|
|
325
|
+
str
|
|
326
|
+
``10`` for ``10`` or ``10.0``, ``0.1`` for ``0.1``, an empty text for None.
|
|
327
|
+
|
|
328
|
+
Examples
|
|
329
|
+
--------
|
|
330
|
+
>>> from numdaplot.tables.columns.bracket_names import write_limit
|
|
331
|
+
>>> write_limit(10.0), write_limit(0.1), write_limit(-3)
|
|
332
|
+
('10', '0.1', '-3')
|
|
333
|
+
"""
|
|
334
|
+
if limit is None:
|
|
335
|
+
return ""
|
|
336
|
+
|
|
337
|
+
decimal_limit = float(limit)
|
|
338
|
+
is_whole = decimal_limit.is_integer()
|
|
339
|
+
if is_whole:
|
|
340
|
+
whole_limit = int(limit)
|
|
341
|
+
whole_text = str(whole_limit)
|
|
342
|
+
return whole_text
|
|
343
|
+
|
|
344
|
+
shortest_text = repr(limit)
|
|
345
|
+
|
|
346
|
+
return shortest_text
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Conversion of a number column to the categories of its brackets.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, cast
|
|
8
|
+
|
|
9
|
+
import numpy
|
|
10
|
+
import pandas
|
|
11
|
+
from numpy.typing import NDArray
|
|
12
|
+
|
|
13
|
+
from numdaplot.arrays.mapping.unmatched import Unmatched
|
|
14
|
+
from numdaplot.data_types.pandas_mapping import to_pandas_dtype
|
|
15
|
+
from numdaplot.data_types.type import Type
|
|
16
|
+
from numdaplot.errors.unmatched_value_error import BRACKETS_NAME, UnmatchedValueError
|
|
17
|
+
from numdaplot.rules.bounds import Bounds
|
|
18
|
+
from numdaplot.tables.columns.bracket_end import BracketEnd
|
|
19
|
+
from numdaplot.tables.columns.bracket_names import write_bracket_names
|
|
20
|
+
from numdaplot.tables.columns.brackets import Brackets
|
|
21
|
+
from numdaplot.tables.frames.column import Column
|
|
22
|
+
from numdaplot.tables.frames.column_values import find_column_missing, find_column_type
|
|
23
|
+
from numdaplot.tables.frames.frame_normalization import convert_to_type
|
|
24
|
+
|
|
25
|
+
INTEGER_TYPES = frozenset(
|
|
26
|
+
{Type.INT8, Type.INT16, Type.INT32, Type.INT64, Type.UINT8, Type.UINT16, Type.UINT32, Type.UINT64}
|
|
27
|
+
)
|
|
28
|
+
NO_CATEGORY = -1
|
|
29
|
+
DECIMAL_DTYPE = numpy.float64
|
|
30
|
+
LOW_SIDE = "right"
|
|
31
|
+
HIGH_SIDE = "left"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def cut_column(column: Column, brackets: Brackets) -> Column:
|
|
35
|
+
"""
|
|
36
|
+
Return a number column as the categories of its brackets, in the order of the brackets.
|
|
37
|
+
|
|
38
|
+
.. versionadded:: 0.1.0
|
|
39
|
+
|
|
40
|
+
Parameters
|
|
41
|
+
----------
|
|
42
|
+
column
|
|
43
|
+
A Table column of numbers.
|
|
44
|
+
brackets
|
|
45
|
+
The limits, the bounds, the open ends, the labels and what happens to a value in no bracket.
|
|
46
|
+
|
|
47
|
+
Returns
|
|
48
|
+
-------
|
|
49
|
+
Column
|
|
50
|
+
A ``CATEGORY`` column whose categories are the names of the brackets, missing values staying missing.
|
|
51
|
+
|
|
52
|
+
Raises
|
|
53
|
+
------
|
|
54
|
+
InvalidLimitsError
|
|
55
|
+
When a bracket between two limits holds no integer of a column of integers.
|
|
56
|
+
UnmatchedValueError
|
|
57
|
+
At the first value in no bracket, when ``others`` is ``Unmatched.ERROR``.
|
|
58
|
+
|
|
59
|
+
Examples
|
|
60
|
+
--------
|
|
61
|
+
>>> import pandas
|
|
62
|
+
>>> import numdaplot as ndp
|
|
63
|
+
>>> from numdaplot.tables.columns.bracketed_column import cut_column
|
|
64
|
+
>>> ages = pandas.Series([4, None, 30], dtype="Int64")
|
|
65
|
+
>>> cut_column(ages, ndp.Brackets(limits=[0, 18, 65])).tolist()
|
|
66
|
+
['0 to 17', <NA>, '18 to 64']
|
|
67
|
+
"""
|
|
68
|
+
column_type = find_column_type(column)
|
|
69
|
+
holds_integers = column_type in INTEGER_TYPES
|
|
70
|
+
names = write_bracket_names(brackets, holds_integers)
|
|
71
|
+
missing = find_column_missing(column)
|
|
72
|
+
numbers = column.to_numpy(dtype=DECIMAL_DTYPE, na_value=numpy.nan)
|
|
73
|
+
positions = find_bracket_positions(numbers, brackets)
|
|
74
|
+
has_no_bracket = positions == NO_CATEGORY
|
|
75
|
+
unmatched = has_no_bracket & ~missing
|
|
76
|
+
require_matched_values(column, unmatched, brackets.others)
|
|
77
|
+
text_dtype = to_pandas_dtype(Type.TEXT)
|
|
78
|
+
categories = pandas.Index(names, dtype=text_dtype)
|
|
79
|
+
# Some versions of the pandas stubs only accept a sequence of integers as codes.
|
|
80
|
+
categorical_class = cast(Any, pandas.Categorical)
|
|
81
|
+
raw_categorical = categorical_class.from_codes(positions, categories=categories)
|
|
82
|
+
categorical = cast(pandas.Categorical, raw_categorical)
|
|
83
|
+
category_column = pandas.Series(categorical, index=column.index)
|
|
84
|
+
stored_column = convert_to_type(category_column, Type.CATEGORY)
|
|
85
|
+
|
|
86
|
+
return stored_column
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def find_bracket_positions(numbers: NDArray[numpy.float64], brackets: Brackets) -> NDArray[numpy.intp]:
|
|
90
|
+
"""
|
|
91
|
+
Return the position of the bracket of each number, -1 for a missing number or a number in no bracket.
|
|
92
|
+
|
|
93
|
+
.. versionadded:: 0.1.0
|
|
94
|
+
|
|
95
|
+
Parameters
|
|
96
|
+
----------
|
|
97
|
+
numbers
|
|
98
|
+
The numbers, NaN where missing.
|
|
99
|
+
brackets
|
|
100
|
+
The limits, the bounds and the open ends.
|
|
101
|
+
|
|
102
|
+
Returns
|
|
103
|
+
-------
|
|
104
|
+
NDArray[numpy.intp]
|
|
105
|
+
The position of each bracket, counted from the first one, open or not.
|
|
106
|
+
|
|
107
|
+
Examples
|
|
108
|
+
--------
|
|
109
|
+
>>> import numpy
|
|
110
|
+
>>> import numdaplot as ndp
|
|
111
|
+
>>> from numdaplot.tables.columns.bracketed_column import find_bracket_positions
|
|
112
|
+
>>> brackets = ndp.Brackets(limits=[0, 10, 20], first=ndp.BracketEnd.OPEN)
|
|
113
|
+
>>> find_bracket_positions(numpy.array([-5.0, 0.0, 10.0, 25.0, numpy.nan]), brackets)
|
|
114
|
+
array([ 0, 1, 2, -1, -1])
|
|
115
|
+
"""
|
|
116
|
+
limits = numpy.array(brackets.limits, dtype=DECIMAL_DTYPE)
|
|
117
|
+
side = LOW_SIDE if brackets.bounds == Bounds.LOW_ONLY else HIGH_SIDE
|
|
118
|
+
limit_counts = numpy.searchsorted(limits, numbers, side=side)
|
|
119
|
+
first_offset = 1 if brackets.first == BracketEnd.OPEN else 0
|
|
120
|
+
positions = limit_counts - 1 + first_offset
|
|
121
|
+
is_matched = ~numpy.isnan(numbers)
|
|
122
|
+
if brackets.first == BracketEnd.CLOSED:
|
|
123
|
+
is_above_first = limit_counts > 0
|
|
124
|
+
is_matched = is_matched & is_above_first
|
|
125
|
+
|
|
126
|
+
if brackets.last == BracketEnd.CLOSED:
|
|
127
|
+
limit_count = limits.size
|
|
128
|
+
is_below_last = limit_counts < limit_count
|
|
129
|
+
is_matched = is_matched & is_below_last
|
|
130
|
+
|
|
131
|
+
matched_positions = numpy.where(is_matched, positions, NO_CATEGORY)
|
|
132
|
+
|
|
133
|
+
return matched_positions
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def require_matched_values(column: Column, unmatched: NDArray[numpy.bool_], others: Unmatched) -> None:
|
|
137
|
+
"""
|
|
138
|
+
Check that every present number is in a bracket, unless the numbers in no bracket become missing.
|
|
139
|
+
|
|
140
|
+
.. versionadded:: 0.1.0
|
|
141
|
+
|
|
142
|
+
Parameters
|
|
143
|
+
----------
|
|
144
|
+
column
|
|
145
|
+
The Table column of numbers.
|
|
146
|
+
unmatched
|
|
147
|
+
True at each present number in no bracket.
|
|
148
|
+
others
|
|
149
|
+
``Unmatched.ERROR`` to refuse such a number, ``Unmatched.MISSING`` to make it missing.
|
|
150
|
+
|
|
151
|
+
Raises
|
|
152
|
+
------
|
|
153
|
+
UnmatchedValueError
|
|
154
|
+
At the first number in no bracket, with ``Unmatched.ERROR``.
|
|
155
|
+
|
|
156
|
+
Examples
|
|
157
|
+
--------
|
|
158
|
+
>>> import numpy
|
|
159
|
+
>>> import pandas
|
|
160
|
+
>>> import numdaplot as ndp
|
|
161
|
+
>>> from numdaplot.tables.columns.bracketed_column import require_matched_values
|
|
162
|
+
>>> try:
|
|
163
|
+
... require_matched_values(pandas.Series([5, 105]), numpy.array([False, True]), ndp.Unmatched.ERROR)
|
|
164
|
+
... except ndp.UnmatchedValueError as error:
|
|
165
|
+
... print(error.value)
|
|
166
|
+
105
|
|
167
|
+
"""
|
|
168
|
+
if others == Unmatched.MISSING:
|
|
169
|
+
return
|
|
170
|
+
|
|
171
|
+
has_unmatched = bool(unmatched.any())
|
|
172
|
+
if not has_unmatched:
|
|
173
|
+
return
|
|
174
|
+
|
|
175
|
+
unmatched_positions = numpy.flatnonzero(unmatched)
|
|
176
|
+
first_position = int(unmatched_positions[0])
|
|
177
|
+
python_values = column.tolist()
|
|
178
|
+
first_value = python_values[first_position]
|
|
179
|
+
raise UnmatchedValueError(first_value, BRACKETS_NAME)
|