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,593 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Check of the settings of an object against the annotations of its fields.
|
|
3
|
+
|
|
4
|
+
The annotations are the only description of what a setting accepts, so a check and a signature never disagree.
|
|
5
|
+
|
|
6
|
+
.. versionadded:: 0.1.0
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import dataclasses
|
|
10
|
+
import functools
|
|
11
|
+
import importlib
|
|
12
|
+
import types
|
|
13
|
+
import typing
|
|
14
|
+
from collections.abc import Sequence
|
|
15
|
+
from dataclasses import dataclass
|
|
16
|
+
from typing import Any, cast
|
|
17
|
+
|
|
18
|
+
import numpy
|
|
19
|
+
|
|
20
|
+
from numdaplot.errors.invalid_type_error import InvalidTypeError
|
|
21
|
+
|
|
22
|
+
PACKAGE_NAME = "numdaplot"
|
|
23
|
+
NONE_NAME = "None"
|
|
24
|
+
VOWELS = "aeiouAEIOU"
|
|
25
|
+
# These words start with a vowel letter but with a consonant sound, as in "a Uniform".
|
|
26
|
+
CONSONANT_SOUND_PREFIXES = ("Uni",)
|
|
27
|
+
ARTICLE_FORMAT = "{article} {name}"
|
|
28
|
+
NAMES_SEPARATOR = ", "
|
|
29
|
+
LAST_NAME_FORMAT = "{names} or {last_name}"
|
|
30
|
+
LIST_OF_FORMAT = "a list of {names}"
|
|
31
|
+
ANY_LIST = "a list"
|
|
32
|
+
LIST_SUCH_AS_FORMAT = "a list such as [{text!r}]"
|
|
33
|
+
SETTING_NAME_FORMAT = "{owner_name} {field_name}"
|
|
34
|
+
NUMBER_CLASSES = dict[object, tuple[type, ...]](
|
|
35
|
+
{
|
|
36
|
+
bool: (bool, numpy.bool_),
|
|
37
|
+
int: (int, numpy.integer),
|
|
38
|
+
float: (int, float, numpy.integer, numpy.floating),
|
|
39
|
+
}
|
|
40
|
+
)
|
|
41
|
+
UNION_ORIGINS = (typing.Union, types.UnionType)
|
|
42
|
+
LIST_ORIGINS = (list, Sequence)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass(frozen=True)
|
|
46
|
+
class AcceptedKinds:
|
|
47
|
+
"""
|
|
48
|
+
What a setting accepts, read from its annotation.
|
|
49
|
+
|
|
50
|
+
.. versionadded:: 0.1.0
|
|
51
|
+
|
|
52
|
+
Parameters
|
|
53
|
+
----------
|
|
54
|
+
classes
|
|
55
|
+
The accepted classes.
|
|
56
|
+
list_items
|
|
57
|
+
What the items of a list accept, or None when a list is not accepted.
|
|
58
|
+
names
|
|
59
|
+
The names of the accepted classes, in the order of the annotation, a list being left out.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
classes: tuple[type, ...]
|
|
63
|
+
list_items: "AcceptedKinds | None"
|
|
64
|
+
names: tuple[str, ...]
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@dataclass(frozen=True)
|
|
68
|
+
class FieldCheck:
|
|
69
|
+
"""
|
|
70
|
+
One field of a setting object, and what it accepts.
|
|
71
|
+
|
|
72
|
+
.. versionadded:: 0.1.0
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
field_name
|
|
77
|
+
The name of the field.
|
|
78
|
+
setting_name
|
|
79
|
+
The name shown in the error message, such as ``"Region rows"``.
|
|
80
|
+
kinds
|
|
81
|
+
What the field accepts.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
field_name: str
|
|
85
|
+
setting_name: str
|
|
86
|
+
kinds: AcceptedKinds
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def require_field_types(setting: object) -> None:
|
|
90
|
+
"""
|
|
91
|
+
Check that every field of a setting object holds a value accepted by its annotation.
|
|
92
|
+
|
|
93
|
+
.. versionadded:: 0.1.0
|
|
94
|
+
|
|
95
|
+
Parameters
|
|
96
|
+
----------
|
|
97
|
+
setting
|
|
98
|
+
The dataclass instance to check.
|
|
99
|
+
|
|
100
|
+
Raises
|
|
101
|
+
------
|
|
102
|
+
InvalidTypeError
|
|
103
|
+
At the first field holding a value its annotation does not accept.
|
|
104
|
+
|
|
105
|
+
Examples
|
|
106
|
+
--------
|
|
107
|
+
>>> import numdaplot as ndp
|
|
108
|
+
>>> from numdaplot.settings.field_types import require_field_types
|
|
109
|
+
>>> require_field_types(ndp.Index(1))
|
|
110
|
+
>>> try:
|
|
111
|
+
... ndp.Preview(count="2")
|
|
112
|
+
... except ndp.InvalidTypeError as error:
|
|
113
|
+
... print(error)
|
|
114
|
+
Preview count expects an int, got '2'.
|
|
115
|
+
"""
|
|
116
|
+
setting_class = type(setting)
|
|
117
|
+
field_checks = find_field_checks(setting_class)
|
|
118
|
+
|
|
119
|
+
for field_check in field_checks:
|
|
120
|
+
value = getattr(setting, field_check.field_name)
|
|
121
|
+
is_accepted = accepts_value(field_check.kinds, value)
|
|
122
|
+
if not is_accepted:
|
|
123
|
+
expected = describe_kinds(field_check.kinds, value)
|
|
124
|
+
rejected_value = find_rejected_value(field_check.kinds, value)
|
|
125
|
+
raise InvalidTypeError(field_check.setting_name, expected, rejected_value)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@functools.cache
|
|
129
|
+
def find_field_checks(setting_class: type) -> tuple[FieldCheck, ...]:
|
|
130
|
+
"""
|
|
131
|
+
Return the checks of the fields of a dataclass, built once for each class.
|
|
132
|
+
|
|
133
|
+
.. versionadded:: 0.1.0
|
|
134
|
+
|
|
135
|
+
Parameters
|
|
136
|
+
----------
|
|
137
|
+
setting_class
|
|
138
|
+
The dataclass.
|
|
139
|
+
|
|
140
|
+
Returns
|
|
141
|
+
-------
|
|
142
|
+
tuple[FieldCheck, ...]
|
|
143
|
+
One check per field.
|
|
144
|
+
|
|
145
|
+
Examples
|
|
146
|
+
--------
|
|
147
|
+
>>> import numdaplot as ndp
|
|
148
|
+
>>> from numdaplot.settings.field_types import find_field_checks
|
|
149
|
+
>>> find_field_checks(ndp.Index)[0].setting_name
|
|
150
|
+
'Index position'
|
|
151
|
+
"""
|
|
152
|
+
annotations = read_annotations(setting_class)
|
|
153
|
+
field_checks = list[FieldCheck]()
|
|
154
|
+
dataclass_fields = dataclasses.fields(setting_class)
|
|
155
|
+
|
|
156
|
+
for dataclass_field in dataclass_fields:
|
|
157
|
+
field_name = dataclass_field.name
|
|
158
|
+
setting_name = SETTING_NAME_FORMAT.format(owner_name=setting_class.__name__, field_name=field_name)
|
|
159
|
+
kinds = read_accepted_kinds(annotations[field_name])
|
|
160
|
+
field_check = FieldCheck(field_name, setting_name, kinds)
|
|
161
|
+
field_checks.append(field_check)
|
|
162
|
+
|
|
163
|
+
return tuple(field_checks)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def read_annotations(annotated: Any) -> dict[str, Any]:
|
|
167
|
+
"""
|
|
168
|
+
Return the annotations of a class or a function, resolving the names only known to the type checker.
|
|
169
|
+
|
|
170
|
+
Array and its settings refer to each other, so some annotations are texts naming a class that their module
|
|
171
|
+
cannot import. Those names are looked up in numdaplot at the first call, when it is entirely imported.
|
|
172
|
+
|
|
173
|
+
.. versionadded:: 0.1.0
|
|
174
|
+
|
|
175
|
+
Parameters
|
|
176
|
+
----------
|
|
177
|
+
annotated
|
|
178
|
+
The class or the function.
|
|
179
|
+
|
|
180
|
+
Returns
|
|
181
|
+
-------
|
|
182
|
+
dict[str, Any]
|
|
183
|
+
The annotation of each field or parameter.
|
|
184
|
+
|
|
185
|
+
Examples
|
|
186
|
+
--------
|
|
187
|
+
>>> import numdaplot as ndp
|
|
188
|
+
>>> from numdaplot.settings.field_types import read_annotations
|
|
189
|
+
>>> read_annotations(ndp.Index)["position"]
|
|
190
|
+
<class 'int'>
|
|
191
|
+
"""
|
|
192
|
+
try:
|
|
193
|
+
annotations = typing.get_type_hints(annotated)
|
|
194
|
+
except NameError:
|
|
195
|
+
package = importlib.import_module(PACKAGE_NAME)
|
|
196
|
+
package_names = vars(package)
|
|
197
|
+
annotations = typing.get_type_hints(annotated, localns=package_names)
|
|
198
|
+
|
|
199
|
+
return annotations
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def read_accepted_kinds(annotation: object, open_aliases: frozenset[object] = frozenset()) -> AcceptedKinds:
|
|
203
|
+
"""
|
|
204
|
+
Return what an annotation accepts, going through its aliases, its type parameters and its unions.
|
|
205
|
+
|
|
206
|
+
.. versionadded:: 0.1.0
|
|
207
|
+
|
|
208
|
+
Parameters
|
|
209
|
+
----------
|
|
210
|
+
annotation
|
|
211
|
+
The annotation of a field.
|
|
212
|
+
open_aliases
|
|
213
|
+
The aliases being expanded, none by default.
|
|
214
|
+
|
|
215
|
+
Returns
|
|
216
|
+
-------
|
|
217
|
+
AcceptedKinds
|
|
218
|
+
The accepted classes, and what the items of a list accept.
|
|
219
|
+
|
|
220
|
+
Examples
|
|
221
|
+
--------
|
|
222
|
+
>>> import numdaplot as ndp
|
|
223
|
+
>>> from numdaplot.settings.field_types import read_accepted_kinds
|
|
224
|
+
>>> read_accepted_kinds(ndp.Side | None).names
|
|
225
|
+
('Side', 'None')
|
|
226
|
+
"""
|
|
227
|
+
classes = list[type]()
|
|
228
|
+
names = list[str]()
|
|
229
|
+
list_items = None
|
|
230
|
+
expanded_aliases = open_aliases
|
|
231
|
+
if isinstance(annotation, typing.TypeAliasType):
|
|
232
|
+
expanded_aliases = open_aliases | {annotation}
|
|
233
|
+
|
|
234
|
+
members = list_annotation_members(annotation, open_aliases)
|
|
235
|
+
|
|
236
|
+
for member in members:
|
|
237
|
+
origin = typing.get_origin(member)
|
|
238
|
+
if origin in LIST_ORIGINS:
|
|
239
|
+
item_annotation = typing.get_args(member)[0]
|
|
240
|
+
list_items = read_accepted_kinds(item_annotation, expanded_aliases)
|
|
241
|
+
continue
|
|
242
|
+
|
|
243
|
+
member_classes = find_member_classes(member)
|
|
244
|
+
classes.extend(member_classes)
|
|
245
|
+
member_name = find_member_name(member)
|
|
246
|
+
names.append(member_name)
|
|
247
|
+
|
|
248
|
+
return AcceptedKinds(tuple(classes), list_items, tuple(names))
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def list_annotation_members(annotation: object, open_aliases: frozenset[object] = frozenset()) -> list[object]:
|
|
252
|
+
"""
|
|
253
|
+
Return the members of an annotation, with its aliases, its type parameters and its unions expanded.
|
|
254
|
+
|
|
255
|
+
.. versionadded:: 0.1.0
|
|
256
|
+
|
|
257
|
+
Parameters
|
|
258
|
+
----------
|
|
259
|
+
annotation
|
|
260
|
+
The annotation.
|
|
261
|
+
open_aliases
|
|
262
|
+
The aliases being expanded, none by default.
|
|
263
|
+
|
|
264
|
+
Returns
|
|
265
|
+
-------
|
|
266
|
+
list[object]
|
|
267
|
+
The classes and the list annotations it accepts.
|
|
268
|
+
|
|
269
|
+
Examples
|
|
270
|
+
--------
|
|
271
|
+
>>> from numdaplot.settings.field_types import list_annotation_members
|
|
272
|
+
>>> list_annotation_members(int | None)
|
|
273
|
+
[<class 'int'>, <class 'NoneType'>]
|
|
274
|
+
"""
|
|
275
|
+
if isinstance(annotation, typing.TypeAliasType):
|
|
276
|
+
# An alias naming itself, such as nested lists, accepts anything at its deeper levels.
|
|
277
|
+
if annotation in open_aliases:
|
|
278
|
+
return [typing.Any]
|
|
279
|
+
|
|
280
|
+
aliased_members = list_annotation_members(annotation.__value__, open_aliases | {annotation})
|
|
281
|
+
return aliased_members
|
|
282
|
+
|
|
283
|
+
nested_annotations = None
|
|
284
|
+
if isinstance(annotation, typing.TypeVar):
|
|
285
|
+
# A type parameter without constraint accepts anything.
|
|
286
|
+
nested_annotations = annotation.__constraints__ or (typing.Any,)
|
|
287
|
+
|
|
288
|
+
origin = typing.get_origin(annotation)
|
|
289
|
+
if isinstance(origin, typing.TypeAliasType):
|
|
290
|
+
nested_annotations = (origin.__value__,)
|
|
291
|
+
|
|
292
|
+
if origin in UNION_ORIGINS:
|
|
293
|
+
nested_annotations = typing.get_args(annotation)
|
|
294
|
+
|
|
295
|
+
if nested_annotations is None:
|
|
296
|
+
return [annotation]
|
|
297
|
+
|
|
298
|
+
members = list[object]()
|
|
299
|
+
|
|
300
|
+
for nested_annotation in nested_annotations:
|
|
301
|
+
nested_members = list_annotation_members(nested_annotation, open_aliases)
|
|
302
|
+
members.extend(nested_members)
|
|
303
|
+
|
|
304
|
+
return members
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def find_member_classes(member: object) -> tuple[type, ...]:
|
|
308
|
+
"""
|
|
309
|
+
Return the classes a member of an annotation accepts: numbers from numpy count as Python numbers.
|
|
310
|
+
|
|
311
|
+
.. versionadded:: 0.1.0
|
|
312
|
+
|
|
313
|
+
Parameters
|
|
314
|
+
----------
|
|
315
|
+
member
|
|
316
|
+
A class, or ``typing.Any`` which accepts everything.
|
|
317
|
+
|
|
318
|
+
Returns
|
|
319
|
+
-------
|
|
320
|
+
tuple[type, ...]
|
|
321
|
+
The accepted classes.
|
|
322
|
+
|
|
323
|
+
Examples
|
|
324
|
+
--------
|
|
325
|
+
>>> from numdaplot.settings.field_types import find_member_classes
|
|
326
|
+
>>> find_member_classes(str)
|
|
327
|
+
(<class 'str'>,)
|
|
328
|
+
"""
|
|
329
|
+
if member is typing.Any:
|
|
330
|
+
return (object,)
|
|
331
|
+
|
|
332
|
+
if member in NUMBER_CLASSES:
|
|
333
|
+
return NUMBER_CLASSES[member]
|
|
334
|
+
|
|
335
|
+
origin = typing.get_origin(member)
|
|
336
|
+
if origin is not None:
|
|
337
|
+
return (cast(type, origin),)
|
|
338
|
+
|
|
339
|
+
return (cast(type, member),)
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def find_member_name(member: object) -> str:
|
|
343
|
+
"""
|
|
344
|
+
Return the name of a member of an annotation, as shown in the error message.
|
|
345
|
+
|
|
346
|
+
.. versionadded:: 0.1.0
|
|
347
|
+
|
|
348
|
+
Parameters
|
|
349
|
+
----------
|
|
350
|
+
member
|
|
351
|
+
A class, or ``typing.Any``.
|
|
352
|
+
|
|
353
|
+
Returns
|
|
354
|
+
-------
|
|
355
|
+
str
|
|
356
|
+
The name of the class, ``None`` for the type of None.
|
|
357
|
+
|
|
358
|
+
Examples
|
|
359
|
+
--------
|
|
360
|
+
>>> from numdaplot.settings.field_types import find_member_name
|
|
361
|
+
>>> find_member_name(type(None))
|
|
362
|
+
'None'
|
|
363
|
+
"""
|
|
364
|
+
if member is types.NoneType:
|
|
365
|
+
return NONE_NAME
|
|
366
|
+
|
|
367
|
+
origin = typing.get_origin(member)
|
|
368
|
+
named_member = member if origin is None else origin
|
|
369
|
+
member_name = getattr(named_member, "__name__", str(named_member))
|
|
370
|
+
|
|
371
|
+
return member_name
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def accepts_value(kinds: AcceptedKinds, value: object) -> bool:
|
|
375
|
+
"""
|
|
376
|
+
Return whether a value is of an accepted kind, every item of a list included.
|
|
377
|
+
|
|
378
|
+
A boolean is a Python integer, yet it is only accepted where the annotation names ``bool``.
|
|
379
|
+
|
|
380
|
+
.. versionadded:: 0.1.0
|
|
381
|
+
|
|
382
|
+
Parameters
|
|
383
|
+
----------
|
|
384
|
+
kinds
|
|
385
|
+
What the setting accepts.
|
|
386
|
+
value
|
|
387
|
+
The value.
|
|
388
|
+
|
|
389
|
+
Returns
|
|
390
|
+
-------
|
|
391
|
+
bool
|
|
392
|
+
True when the value is accepted.
|
|
393
|
+
|
|
394
|
+
Examples
|
|
395
|
+
--------
|
|
396
|
+
>>> from numdaplot.settings.field_types import accepts_value, read_accepted_kinds
|
|
397
|
+
>>> accepts_value(read_accepted_kinds(int), True)
|
|
398
|
+
False
|
|
399
|
+
>>> accepts_value(read_accepted_kinds(list[str]), ["a", 1])
|
|
400
|
+
False
|
|
401
|
+
"""
|
|
402
|
+
if object in kinds.classes:
|
|
403
|
+
return True
|
|
404
|
+
|
|
405
|
+
if isinstance(value, bool):
|
|
406
|
+
return bool in kinds.classes
|
|
407
|
+
|
|
408
|
+
if isinstance(value, kinds.classes):
|
|
409
|
+
return True
|
|
410
|
+
|
|
411
|
+
if kinds.list_items is None or not isinstance(value, list):
|
|
412
|
+
return False
|
|
413
|
+
|
|
414
|
+
items = cast(list[object], value)
|
|
415
|
+
|
|
416
|
+
for item in items:
|
|
417
|
+
is_item_accepted = accepts_value(kinds.list_items, item)
|
|
418
|
+
if not is_item_accepted:
|
|
419
|
+
return False
|
|
420
|
+
|
|
421
|
+
return True
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def find_rejected_value(kinds: AcceptedKinds, value: object) -> object:
|
|
425
|
+
"""
|
|
426
|
+
Return what to show in the error message: the first rejected item of a list, or the rejected value.
|
|
427
|
+
|
|
428
|
+
.. versionadded:: 0.1.0
|
|
429
|
+
|
|
430
|
+
Parameters
|
|
431
|
+
----------
|
|
432
|
+
kinds
|
|
433
|
+
What the setting accepts.
|
|
434
|
+
value
|
|
435
|
+
The rejected value.
|
|
436
|
+
|
|
437
|
+
Returns
|
|
438
|
+
-------
|
|
439
|
+
object
|
|
440
|
+
The first rejected item when the value is a list of accepted kind, the value otherwise.
|
|
441
|
+
|
|
442
|
+
Examples
|
|
443
|
+
--------
|
|
444
|
+
>>> from numdaplot.settings.field_types import find_rejected_value, read_accepted_kinds
|
|
445
|
+
>>> find_rejected_value(read_accepted_kinds(list[str]), ["a", 1])
|
|
446
|
+
1
|
|
447
|
+
"""
|
|
448
|
+
if kinds.list_items is None or not isinstance(value, list):
|
|
449
|
+
return value
|
|
450
|
+
|
|
451
|
+
items = cast(list[object], value)
|
|
452
|
+
|
|
453
|
+
for item in items:
|
|
454
|
+
is_item_accepted = accepts_value(kinds.list_items, item)
|
|
455
|
+
if not is_item_accepted:
|
|
456
|
+
return item
|
|
457
|
+
|
|
458
|
+
return items
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def describe_kinds(kinds: AcceptedKinds, value: object) -> str:
|
|
462
|
+
"""
|
|
463
|
+
Return what a setting accepts, as written in the error message.
|
|
464
|
+
|
|
465
|
+
A text given in place of a list is shown inside a list, the most likely thing to write.
|
|
466
|
+
|
|
467
|
+
.. versionadded:: 0.1.0
|
|
468
|
+
|
|
469
|
+
Parameters
|
|
470
|
+
----------
|
|
471
|
+
kinds
|
|
472
|
+
What the setting accepts.
|
|
473
|
+
value
|
|
474
|
+
The rejected value.
|
|
475
|
+
|
|
476
|
+
Returns
|
|
477
|
+
-------
|
|
478
|
+
str
|
|
479
|
+
The description, such as ``an Index, a Range or None``.
|
|
480
|
+
|
|
481
|
+
Examples
|
|
482
|
+
--------
|
|
483
|
+
>>> from numdaplot.settings.field_types import describe_kinds, read_accepted_kinds
|
|
484
|
+
>>> describe_kinds(read_accepted_kinds(list[str]), "price")
|
|
485
|
+
"a list such as ['price']"
|
|
486
|
+
>>> describe_kinds(read_accepted_kinds(int | None), "2")
|
|
487
|
+
'an int or None'
|
|
488
|
+
"""
|
|
489
|
+
if kinds.list_items is not None and isinstance(value, str):
|
|
490
|
+
return LIST_SUCH_AS_FORMAT.format(text=value)
|
|
491
|
+
|
|
492
|
+
descriptions = [add_article(name) for name in kinds.names]
|
|
493
|
+
if kinds.list_items is not None:
|
|
494
|
+
list_description = describe_list(kinds.list_items)
|
|
495
|
+
descriptions.append(list_description)
|
|
496
|
+
|
|
497
|
+
description = join_names(descriptions)
|
|
498
|
+
|
|
499
|
+
return description
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
def describe_list(list_items: AcceptedKinds) -> str:
|
|
503
|
+
"""
|
|
504
|
+
Return what a list accepts, as written in the error message.
|
|
505
|
+
|
|
506
|
+
.. versionadded:: 0.1.0
|
|
507
|
+
|
|
508
|
+
Parameters
|
|
509
|
+
----------
|
|
510
|
+
list_items
|
|
511
|
+
What the items of the list accept.
|
|
512
|
+
|
|
513
|
+
Returns
|
|
514
|
+
-------
|
|
515
|
+
str
|
|
516
|
+
``a list of str``, or ``a list`` when its items accept anything.
|
|
517
|
+
|
|
518
|
+
Examples
|
|
519
|
+
--------
|
|
520
|
+
>>> from typing import Any
|
|
521
|
+
>>> from numdaplot.settings.field_types import describe_list, read_accepted_kinds
|
|
522
|
+
>>> describe_list(read_accepted_kinds(str)), describe_list(read_accepted_kinds(Any))
|
|
523
|
+
('a list of str', 'a list')
|
|
524
|
+
"""
|
|
525
|
+
if object in list_items.classes:
|
|
526
|
+
return ANY_LIST
|
|
527
|
+
|
|
528
|
+
item_names = join_names(list_items.names)
|
|
529
|
+
|
|
530
|
+
return LIST_OF_FORMAT.format(names=item_names)
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
def add_article(name: str) -> str:
|
|
534
|
+
"""
|
|
535
|
+
Return the name of a class with its article, None staying as it is.
|
|
536
|
+
|
|
537
|
+
.. versionadded:: 0.1.0
|
|
538
|
+
|
|
539
|
+
Parameters
|
|
540
|
+
----------
|
|
541
|
+
name
|
|
542
|
+
The name of a class.
|
|
543
|
+
|
|
544
|
+
Returns
|
|
545
|
+
-------
|
|
546
|
+
str
|
|
547
|
+
The name with ``a`` or ``an``.
|
|
548
|
+
|
|
549
|
+
Examples
|
|
550
|
+
--------
|
|
551
|
+
>>> from numdaplot.settings.field_types import add_article
|
|
552
|
+
>>> add_article("Index"), add_article("Range"), add_article("None")
|
|
553
|
+
('an Index', 'a Range', 'None')
|
|
554
|
+
"""
|
|
555
|
+
if name == NONE_NAME:
|
|
556
|
+
return name
|
|
557
|
+
|
|
558
|
+
starts_with_vowel_sound = name[0] in VOWELS and not name.startswith(CONSONANT_SOUND_PREFIXES)
|
|
559
|
+
article = "an" if starts_with_vowel_sound else "a"
|
|
560
|
+
|
|
561
|
+
return ARTICLE_FORMAT.format(article=article, name=name)
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
def join_names(names: Sequence[str]) -> str:
|
|
565
|
+
"""
|
|
566
|
+
Return names separated by commas, the last one after ``or``.
|
|
567
|
+
|
|
568
|
+
.. versionadded:: 0.1.0
|
|
569
|
+
|
|
570
|
+
Parameters
|
|
571
|
+
----------
|
|
572
|
+
names
|
|
573
|
+
The names, at least one.
|
|
574
|
+
|
|
575
|
+
Returns
|
|
576
|
+
-------
|
|
577
|
+
str
|
|
578
|
+
The joined names.
|
|
579
|
+
|
|
580
|
+
Examples
|
|
581
|
+
--------
|
|
582
|
+
>>> from numdaplot.settings.field_types import join_names
|
|
583
|
+
>>> join_names(["an Index", "a Range", "None"])
|
|
584
|
+
'an Index, a Range or None'
|
|
585
|
+
"""
|
|
586
|
+
first_names = names[:-1]
|
|
587
|
+
last_name = names[-1]
|
|
588
|
+
if not first_names:
|
|
589
|
+
return last_name
|
|
590
|
+
|
|
591
|
+
joined_names = NAMES_SEPARATOR.join(first_names)
|
|
592
|
+
|
|
593
|
+
return LAST_NAME_FORMAT.format(names=joined_names, last_name=last_name)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Number of values statistic.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
|
|
9
|
+
from numdaplot.settings.field_types import require_field_types
|
|
10
|
+
from numdaplot.statistics.counted_missing import CountedMissing
|
|
11
|
+
from numdaplot.statistics.statistic import Statistic
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class Count(Statistic):
|
|
16
|
+
"""
|
|
17
|
+
Number of values, without the missing ones by default.
|
|
18
|
+
|
|
19
|
+
With ``CountedMissing.INCLUDED``, it gives the number of rows of each group of an aggregation, whatever the
|
|
20
|
+
column it is computed on. Use ``count_missing`` to count only the missing values.
|
|
21
|
+
|
|
22
|
+
.. versionadded:: 0.1.0
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
missing
|
|
27
|
+
``CountedMissing.EXCLUDED`` by default to count only the present values, ``CountedMissing.INCLUDED`` to count
|
|
28
|
+
every value.
|
|
29
|
+
|
|
30
|
+
Raises
|
|
31
|
+
------
|
|
32
|
+
InvalidTypeError
|
|
33
|
+
When a setting is not of the type its annotation names.
|
|
34
|
+
|
|
35
|
+
Examples
|
|
36
|
+
--------
|
|
37
|
+
>>> import numdaplot as ndp
|
|
38
|
+
>>> answers = ndp.Array.from_list([4.0, None, 2.0])
|
|
39
|
+
>>> answers.compute(ndp.Count()).to_value()
|
|
40
|
+
2
|
|
41
|
+
>>> answers.compute(ndp.Count(missing=ndp.CountedMissing.INCLUDED)).to_value()
|
|
42
|
+
3
|
|
43
|
+
|
|
44
|
+
The number of rows of each group does not depend on the missing values of the column.
|
|
45
|
+
|
|
46
|
+
>>> colors = ndp.Array.from_list(["green", "green", "yellow"])
|
|
47
|
+
>>> fares = ndp.Array.from_list([7.0, None, 9.0])
|
|
48
|
+
>>> trips = ndp.Table.from_arrays({"color": colors, "fare": fares})
|
|
49
|
+
>>> every_row = ndp.Count(missing=ndp.CountedMissing.INCLUDED)
|
|
50
|
+
>>> trip_count = ndp.Calculation(column="fare", function=every_row, result_name="trip_count")
|
|
51
|
+
>>> trips.aggregate(ndp.Aggregation(calculations=[trip_count], group_by=["color"]))
|
|
52
|
+
color trip_count
|
|
53
|
+
TEXT INT64
|
|
54
|
+
0 green 2
|
|
55
|
+
1 yellow 1
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
missing: CountedMissing = CountedMissing.EXCLUDED
|
|
59
|
+
|
|
60
|
+
def __post_init__(self) -> None:
|
|
61
|
+
"""
|
|
62
|
+
Check the type of the setting.
|
|
63
|
+
|
|
64
|
+
.. versionadded:: 0.1.0
|
|
65
|
+
|
|
66
|
+
Raises
|
|
67
|
+
------
|
|
68
|
+
InvalidTypeError
|
|
69
|
+
When a setting is not of the type its annotation names.
|
|
70
|
+
"""
|
|
71
|
+
require_field_types(self)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Number of distinct values that are not missing statistic.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
|
|
9
|
+
from numdaplot.statistics.statistic import Statistic
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(frozen=True)
|
|
13
|
+
class CountDistinct(Statistic):
|
|
14
|
+
"""
|
|
15
|
+
Number of distinct values that are not missing.
|
|
16
|
+
|
|
17
|
+
``[1, 1, 2]`` gives 2.
|
|
18
|
+
|
|
19
|
+
.. versionadded:: 0.1.0
|
|
20
|
+
|
|
21
|
+
Examples
|
|
22
|
+
--------
|
|
23
|
+
>>> import numdaplot as ndp
|
|
24
|
+
>>> cities = ndp.Array.from_list(["Paris", "Lyon", "Paris"])
|
|
25
|
+
>>> cities.compute(ndp.CountDistinct()).to_value()
|
|
26
|
+
2
|
|
27
|
+
"""
|