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,74 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Settings of the filter of the rows of a Table.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
|
|
9
|
+
from numdaplot.errors.empty_list_error import EmptyListError
|
|
10
|
+
from numdaplot.settings.field_types import require_field_types
|
|
11
|
+
from numdaplot.tables.filtering.condition import Condition
|
|
12
|
+
from numdaplot.tables.filtering.filter_mode import FilterMode
|
|
13
|
+
|
|
14
|
+
CONDITION_ITEM_NAME = "condition"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class Filter:
|
|
19
|
+
"""
|
|
20
|
+
Conditions a row must satisfy to be kept, used by ``Table.filter``.
|
|
21
|
+
|
|
22
|
+
.. versionadded:: 0.1.0
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
conditions
|
|
27
|
+
The conditions, at least one. The filter keeps its own copy of the list.
|
|
28
|
+
mode
|
|
29
|
+
Whether a row must satisfy every condition, ``FilterMode.ALL`` by default, or at least one, ``FilterMode.ANY``.
|
|
30
|
+
|
|
31
|
+
Raises
|
|
32
|
+
------
|
|
33
|
+
InvalidTypeError
|
|
34
|
+
When a setting is not of the type its annotation names.
|
|
35
|
+
EmptyListError
|
|
36
|
+
When ``conditions`` is empty.
|
|
37
|
+
|
|
38
|
+
Examples
|
|
39
|
+
--------
|
|
40
|
+
>>> import numdaplot as ndp
|
|
41
|
+
>>> cities = ndp.Array.from_list(["Paris", "Lyon", "Paris"])
|
|
42
|
+
>>> prices = ndp.Array.from_list([120.0, 80.0, 150.0])
|
|
43
|
+
>>> sales = ndp.Table.from_arrays({"city": cities, "price": prices})
|
|
44
|
+
>>> expensive = ndp.Condition(rule=ndp.Greater(100), columns=["price"])
|
|
45
|
+
>>> in_lyon = ndp.Condition(rule=ndp.Equal("Lyon"), columns=["city"])
|
|
46
|
+
>>> sales.filter(ndp.Filter(conditions=[expensive, in_lyon]))
|
|
47
|
+
city price
|
|
48
|
+
TEXT FLOAT64
|
|
49
|
+
(0 rows)
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
conditions: list[Condition]
|
|
53
|
+
mode: FilterMode = FilterMode.ALL
|
|
54
|
+
|
|
55
|
+
def __post_init__(self) -> None:
|
|
56
|
+
"""
|
|
57
|
+
Check that there is a condition and replace the list with a copy that only the filter holds.
|
|
58
|
+
|
|
59
|
+
.. versionadded:: 0.1.0
|
|
60
|
+
|
|
61
|
+
Raises
|
|
62
|
+
------
|
|
63
|
+
InvalidTypeError
|
|
64
|
+
When a setting is not of the type its annotation names.
|
|
65
|
+
EmptyListError
|
|
66
|
+
When ``conditions`` is empty.
|
|
67
|
+
"""
|
|
68
|
+
require_field_types(self)
|
|
69
|
+
|
|
70
|
+
if self.conditions == []:
|
|
71
|
+
raise EmptyListError(CONDITION_ITEM_NAME)
|
|
72
|
+
|
|
73
|
+
conditions_copy = list(self.conditions)
|
|
74
|
+
object.__setattr__(self, "conditions", conditions_copy)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""
|
|
2
|
+
How the conditions of a Filter combine.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from enum import Enum, auto
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class FilterMode(Enum):
|
|
11
|
+
"""
|
|
12
|
+
How the conditions of a ``Filter`` combine to keep a row.
|
|
13
|
+
|
|
14
|
+
.. versionadded:: 0.1.0
|
|
15
|
+
|
|
16
|
+
Examples
|
|
17
|
+
--------
|
|
18
|
+
>>> import numdaplot as ndp
|
|
19
|
+
>>> cities = ndp.Array.from_list(["Paris", "Lyon", "Paris"])
|
|
20
|
+
>>> prices = ndp.Array.from_list([120.0, 80.0, 150.0])
|
|
21
|
+
>>> sales = ndp.Table.from_arrays({"city": cities, "price": prices})
|
|
22
|
+
>>> expensive = ndp.Condition(rule=ndp.Greater(130), columns=["price"])
|
|
23
|
+
>>> in_lyon = ndp.Condition(rule=ndp.Equal("Lyon"), columns=["city"])
|
|
24
|
+
>>> sales.filter(ndp.Filter(conditions=[expensive, in_lyon], mode=ndp.FilterMode.ANY))
|
|
25
|
+
city price
|
|
26
|
+
TEXT FLOAT64
|
|
27
|
+
0 Lyon 80.0
|
|
28
|
+
1 Paris 150.0
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
ALL = auto()
|
|
32
|
+
"""
|
|
33
|
+
A row is kept when it satisfies every condition. Default value.
|
|
34
|
+
|
|
35
|
+
Examples
|
|
36
|
+
--------
|
|
37
|
+
>>> import numdaplot as ndp
|
|
38
|
+
>>> cities = ndp.Array.from_list(["Paris", "Lyon", "Paris"])
|
|
39
|
+
>>> prices = ndp.Array.from_list([120.0, 80.0, 150.0])
|
|
40
|
+
>>> sales = ndp.Table.from_arrays({"city": cities, "price": prices})
|
|
41
|
+
>>> expensive = ndp.Condition(rule=ndp.Greater(100), columns=["price"])
|
|
42
|
+
>>> in_lyon = ndp.Condition(rule=ndp.Equal("Lyon"), columns=["city"])
|
|
43
|
+
>>> sales.filter(ndp.Filter(conditions=[expensive, in_lyon], mode=ndp.FilterMode.ALL))
|
|
44
|
+
city price
|
|
45
|
+
TEXT FLOAT64
|
|
46
|
+
(0 rows)
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
ANY = auto()
|
|
50
|
+
"""
|
|
51
|
+
A row is kept when it satisfies at least one condition.
|
|
52
|
+
|
|
53
|
+
Examples
|
|
54
|
+
--------
|
|
55
|
+
>>> import numdaplot as ndp
|
|
56
|
+
>>> cities = ndp.Array.from_list(["Paris", "Lyon", "Paris"])
|
|
57
|
+
>>> prices = ndp.Array.from_list([120.0, 80.0, 150.0])
|
|
58
|
+
>>> sales = ndp.Table.from_arrays({"city": cities, "price": prices})
|
|
59
|
+
>>> expensive = ndp.Condition(rule=ndp.Greater(100), columns=["price"])
|
|
60
|
+
>>> in_lyon = ndp.Condition(rule=ndp.Equal("Lyon"), columns=["city"])
|
|
61
|
+
>>> sales.filter(ndp.Filter(conditions=[expensive, in_lyon], mode=ndp.FilterMode.ANY))
|
|
62
|
+
city price
|
|
63
|
+
TEXT FLOAT64
|
|
64
|
+
0 Paris 120.0
|
|
65
|
+
1 Lyon 80.0
|
|
66
|
+
2 Paris 150.0
|
|
67
|
+
"""
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Rows of a Table satisfying a Filter.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import numpy
|
|
8
|
+
import pandas
|
|
9
|
+
from numpy.typing import NDArray
|
|
10
|
+
|
|
11
|
+
from numdaplot.tables.columns.column_names import require_known_columns
|
|
12
|
+
from numdaplot.tables.filtering.column_mask import build_column_mask
|
|
13
|
+
from numdaplot.tables.filtering.column_match import ColumnMatch
|
|
14
|
+
from numdaplot.tables.filtering.condition import Condition
|
|
15
|
+
from numdaplot.tables.filtering.filter import Filter
|
|
16
|
+
from numdaplot.tables.filtering.filter_mode import FilterMode
|
|
17
|
+
|
|
18
|
+
MASK_AXIS = 0
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def build_filter_mask(frame: pandas.DataFrame, row_filter: Filter) -> NDArray[numpy.bool_]:
|
|
22
|
+
"""
|
|
23
|
+
Return which rows of a Table satisfy a Filter.
|
|
24
|
+
|
|
25
|
+
.. versionadded:: 0.1.0
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
frame
|
|
30
|
+
The columns of a Table.
|
|
31
|
+
row_filter
|
|
32
|
+
The conditions and how they combine.
|
|
33
|
+
|
|
34
|
+
Returns
|
|
35
|
+
-------
|
|
36
|
+
NDArray[numpy.bool_]
|
|
37
|
+
True at each row to keep.
|
|
38
|
+
|
|
39
|
+
Raises
|
|
40
|
+
------
|
|
41
|
+
ColumnNotFoundError
|
|
42
|
+
When a condition names a column the Table does not have.
|
|
43
|
+
IncompatibleTypesError
|
|
44
|
+
When a rule does not apply to the type of one of its columns.
|
|
45
|
+
|
|
46
|
+
Examples
|
|
47
|
+
--------
|
|
48
|
+
>>> import pandas
|
|
49
|
+
>>> import numdaplot as ndp
|
|
50
|
+
>>> from numdaplot.tables.filtering.row_mask import build_filter_mask
|
|
51
|
+
>>> frame = pandas.DataFrame({"price": [5.0, 12.0]})
|
|
52
|
+
>>> build_filter_mask(frame, ndp.Filter(conditions=[ndp.Condition(rule=ndp.Greater(10))]))
|
|
53
|
+
array([False, True])
|
|
54
|
+
"""
|
|
55
|
+
condition_masks = [build_condition_mask(frame, condition) for condition in row_filter.conditions]
|
|
56
|
+
requires_all = row_filter.mode == FilterMode.ALL
|
|
57
|
+
row_count = len(frame)
|
|
58
|
+
filter_mask = combine_masks(condition_masks, requires_all, row_count)
|
|
59
|
+
|
|
60
|
+
return filter_mask
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def build_condition_mask(frame: pandas.DataFrame, condition: Condition) -> NDArray[numpy.bool_]:
|
|
64
|
+
"""
|
|
65
|
+
Return which rows of a Table satisfy a Condition.
|
|
66
|
+
|
|
67
|
+
.. versionadded:: 0.1.0
|
|
68
|
+
|
|
69
|
+
Parameters
|
|
70
|
+
----------
|
|
71
|
+
frame
|
|
72
|
+
The columns of a Table.
|
|
73
|
+
condition
|
|
74
|
+
The rule, its columns, and how the columns combine.
|
|
75
|
+
|
|
76
|
+
Returns
|
|
77
|
+
-------
|
|
78
|
+
NDArray[numpy.bool_]
|
|
79
|
+
True at each row satisfying the condition.
|
|
80
|
+
|
|
81
|
+
Raises
|
|
82
|
+
------
|
|
83
|
+
ColumnNotFoundError
|
|
84
|
+
When the condition names a column the Table does not have.
|
|
85
|
+
IncompatibleTypesError
|
|
86
|
+
When the rule does not apply to the type of one of the columns.
|
|
87
|
+
|
|
88
|
+
Examples
|
|
89
|
+
--------
|
|
90
|
+
>>> import pandas
|
|
91
|
+
>>> import numdaplot as ndp
|
|
92
|
+
>>> from numdaplot.tables.filtering.row_mask import build_condition_mask
|
|
93
|
+
>>> frame = pandas.DataFrame({"low": [1.0, 5.0], "high": [2.0, 9.0]})
|
|
94
|
+
>>> build_condition_mask(frame, ndp.Condition(rule=ndp.Greater(1.5), mode=ndp.ColumnMatch.ALL))
|
|
95
|
+
array([False, True])
|
|
96
|
+
"""
|
|
97
|
+
column_names = [str(column_name) for column_name in frame.columns]
|
|
98
|
+
if condition.columns is not None:
|
|
99
|
+
require_known_columns(condition.columns, column_names)
|
|
100
|
+
column_names = condition.columns
|
|
101
|
+
|
|
102
|
+
column_masks = list[NDArray[numpy.bool_]]()
|
|
103
|
+
|
|
104
|
+
for column_name in column_names:
|
|
105
|
+
column = frame[column_name]
|
|
106
|
+
column_mask = build_column_mask(column, condition.rule)
|
|
107
|
+
column_masks.append(column_mask)
|
|
108
|
+
|
|
109
|
+
requires_all = condition.mode == ColumnMatch.ALL
|
|
110
|
+
row_count = len(frame)
|
|
111
|
+
condition_mask = combine_masks(column_masks, requires_all, row_count)
|
|
112
|
+
|
|
113
|
+
return condition_mask
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def combine_masks(masks: list[NDArray[numpy.bool_]], requires_all: bool, row_count: int) -> NDArray[numpy.bool_]:
|
|
117
|
+
"""
|
|
118
|
+
Return the rows satisfying every mask, or at least one mask.
|
|
119
|
+
|
|
120
|
+
.. versionadded:: 0.1.0
|
|
121
|
+
|
|
122
|
+
Parameters
|
|
123
|
+
----------
|
|
124
|
+
masks
|
|
125
|
+
One mask per condition or per column, each as long as the Table.
|
|
126
|
+
requires_all
|
|
127
|
+
True to keep the rows satisfying every mask, False for at least one.
|
|
128
|
+
row_count
|
|
129
|
+
The number of rows of the Table, used when there is no mask.
|
|
130
|
+
|
|
131
|
+
Returns
|
|
132
|
+
-------
|
|
133
|
+
NDArray[numpy.bool_]
|
|
134
|
+
The combined mask. Without any mask, every row satisfies "every mask" and none satisfies "at least one".
|
|
135
|
+
|
|
136
|
+
Examples
|
|
137
|
+
--------
|
|
138
|
+
>>> import numpy
|
|
139
|
+
>>> from numdaplot.tables.filtering.row_mask import combine_masks
|
|
140
|
+
>>> combine_masks([numpy.array([True, False]), numpy.array([True, True])], True, 2)
|
|
141
|
+
array([ True, False])
|
|
142
|
+
"""
|
|
143
|
+
mask_count = len(masks)
|
|
144
|
+
stacked_masks = numpy.array(masks, dtype=numpy.bool_)
|
|
145
|
+
mask_grid = stacked_masks.reshape(mask_count, row_count)
|
|
146
|
+
if requires_all:
|
|
147
|
+
every_mask = numpy.logical_and.reduce(mask_grid, axis=MASK_AXIS)
|
|
148
|
+
return every_mask
|
|
149
|
+
|
|
150
|
+
any_mask = numpy.logical_or.reduce(mask_grid, axis=MASK_AXIS)
|
|
151
|
+
|
|
152
|
+
return any_mask
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Datetimes of a rule matched with the time zone of the column it is applied to.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import dataclasses
|
|
8
|
+
from datetime import UTC, date, datetime
|
|
9
|
+
from typing import Any, cast
|
|
10
|
+
|
|
11
|
+
from numdaplot.dates.time_zone import TimeZone
|
|
12
|
+
from numdaplot.errors.time_zone_mismatch_error import TimeZoneMismatchError
|
|
13
|
+
from numdaplot.rules.rule import Rule
|
|
14
|
+
|
|
15
|
+
NAIVE_COLUMN_OPERATION = "A rule on a column without time zone"
|
|
16
|
+
ZONE_COLUMN_OPERATION = "A rule on a datetime column with a time zone"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def match_rule_time_zone(rule: Rule, time_zone: TimeZone | None) -> Rule:
|
|
20
|
+
"""
|
|
21
|
+
Return a rule whose dates and datetimes can be compared with the values of a column.
|
|
22
|
+
|
|
23
|
+
A column with a time zone is compared through its UTC clock times, so the datetimes of the rule are
|
|
24
|
+
moved to UTC too.
|
|
25
|
+
|
|
26
|
+
.. versionadded:: 0.1.0
|
|
27
|
+
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
rule
|
|
31
|
+
Any rule of numdaplot.
|
|
32
|
+
time_zone
|
|
33
|
+
The time zone of the column, ``None`` when it has none.
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
Rule
|
|
38
|
+
The rule itself for a column without time zone, or a copy with its datetimes as UTC clock times
|
|
39
|
+
without zone.
|
|
40
|
+
|
|
41
|
+
Raises
|
|
42
|
+
------
|
|
43
|
+
TimeZoneMismatchError
|
|
44
|
+
When the rule has a datetime with a time zone and the column has none, or the column has a zone and
|
|
45
|
+
the rule has a date or a datetime without zone.
|
|
46
|
+
|
|
47
|
+
Examples
|
|
48
|
+
--------
|
|
49
|
+
>>> from datetime import datetime
|
|
50
|
+
>>> from zoneinfo import ZoneInfo
|
|
51
|
+
>>> import numdaplot as ndp
|
|
52
|
+
>>> from numdaplot.tables.filtering.rule_moments import match_rule_time_zone
|
|
53
|
+
>>> paris_noon = datetime(2026, 7, 1, 12, tzinfo=ZoneInfo("Europe/Paris"))
|
|
54
|
+
>>> match_rule_time_zone(ndp.Greater(paris_noon), ndp.TimeZone("Europe/Paris"))
|
|
55
|
+
Greater(value=datetime.datetime(2026, 7, 1, 10, 0))
|
|
56
|
+
"""
|
|
57
|
+
if not dataclasses.is_dataclass(rule):
|
|
58
|
+
return rule
|
|
59
|
+
|
|
60
|
+
rule_fields = dataclasses.fields(rule)
|
|
61
|
+
matched_values = dict[str, Any]()
|
|
62
|
+
|
|
63
|
+
for rule_field in rule_fields:
|
|
64
|
+
field_value = getattr(rule, rule_field.name)
|
|
65
|
+
matched_values[rule_field.name] = match_field_time_zone(field_value, time_zone)
|
|
66
|
+
|
|
67
|
+
if time_zone is None:
|
|
68
|
+
return rule
|
|
69
|
+
|
|
70
|
+
matched_rule = dataclasses.replace(rule, **matched_values)
|
|
71
|
+
|
|
72
|
+
return matched_rule
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def match_field_time_zone(field_value: Any, time_zone: TimeZone | None) -> Any:
|
|
76
|
+
"""
|
|
77
|
+
Return the value of a rule setting with its dates and datetimes matched with the zone of a column.
|
|
78
|
+
|
|
79
|
+
.. versionadded:: 0.1.0
|
|
80
|
+
|
|
81
|
+
Parameters
|
|
82
|
+
----------
|
|
83
|
+
field_value
|
|
84
|
+
The value of a setting of a rule, a single value or a list of values.
|
|
85
|
+
time_zone
|
|
86
|
+
The time zone of the column, ``None`` when it has none.
|
|
87
|
+
|
|
88
|
+
Returns
|
|
89
|
+
-------
|
|
90
|
+
Any
|
|
91
|
+
The value, a datetime moved to a UTC clock time without zone, or a list of such values.
|
|
92
|
+
|
|
93
|
+
Raises
|
|
94
|
+
------
|
|
95
|
+
TimeZoneMismatchError
|
|
96
|
+
When a date or a datetime does not match the zone state of the column.
|
|
97
|
+
|
|
98
|
+
Examples
|
|
99
|
+
--------
|
|
100
|
+
>>> from numdaplot.tables.filtering.rule_moments import match_field_time_zone
|
|
101
|
+
>>> match_field_time_zone([1, 2], None)
|
|
102
|
+
[1, 2]
|
|
103
|
+
"""
|
|
104
|
+
if isinstance(field_value, list):
|
|
105
|
+
list_values = cast(list[Any], field_value)
|
|
106
|
+
matched_list = [match_moment_time_zone(list_value, time_zone) for list_value in list_values]
|
|
107
|
+
return matched_list
|
|
108
|
+
|
|
109
|
+
matched_value = match_moment_time_zone(field_value, time_zone)
|
|
110
|
+
|
|
111
|
+
return matched_value
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def match_moment_time_zone(value: Any, time_zone: TimeZone | None) -> Any:
|
|
115
|
+
"""
|
|
116
|
+
Return a single value of a rule with its date or datetime matched with the zone of a column.
|
|
117
|
+
|
|
118
|
+
.. versionadded:: 0.1.0
|
|
119
|
+
|
|
120
|
+
Parameters
|
|
121
|
+
----------
|
|
122
|
+
value
|
|
123
|
+
A single value of a rule.
|
|
124
|
+
time_zone
|
|
125
|
+
The time zone of the column, ``None`` when it has none.
|
|
126
|
+
|
|
127
|
+
Returns
|
|
128
|
+
-------
|
|
129
|
+
Any
|
|
130
|
+
The value itself, or a datetime with a zone moved to a UTC clock time without zone.
|
|
131
|
+
|
|
132
|
+
Raises
|
|
133
|
+
------
|
|
134
|
+
TimeZoneMismatchError
|
|
135
|
+
When the value is a datetime with a zone and the column has none, or the column has a zone and the value
|
|
136
|
+
is a date or a datetime without zone.
|
|
137
|
+
|
|
138
|
+
Examples
|
|
139
|
+
--------
|
|
140
|
+
>>> from datetime import datetime
|
|
141
|
+
>>> from zoneinfo import ZoneInfo
|
|
142
|
+
>>> import numdaplot as ndp
|
|
143
|
+
>>> from numdaplot.tables.filtering.rule_moments import match_moment_time_zone
|
|
144
|
+
>>> match_moment_time_zone(datetime(2026, 1, 1, 9, tzinfo=ZoneInfo("Europe/Paris")), ndp.TimeZone("UTC"))
|
|
145
|
+
datetime.datetime(2026, 1, 1, 8, 0)
|
|
146
|
+
"""
|
|
147
|
+
if not isinstance(value, date):
|
|
148
|
+
return value
|
|
149
|
+
|
|
150
|
+
has_zone = isinstance(value, datetime) and value.tzinfo is not None
|
|
151
|
+
if time_zone is None and has_zone:
|
|
152
|
+
raise TimeZoneMismatchError(NAIVE_COLUMN_OPERATION, False)
|
|
153
|
+
|
|
154
|
+
if time_zone is None:
|
|
155
|
+
return value
|
|
156
|
+
|
|
157
|
+
if not has_zone:
|
|
158
|
+
raise TimeZoneMismatchError(ZONE_COLUMN_OPERATION, True)
|
|
159
|
+
|
|
160
|
+
zone_datetime = cast(datetime, value)
|
|
161
|
+
utc_datetime = zone_datetime.astimezone(UTC)
|
|
162
|
+
naive_datetime = utc_datetime.replace(tzinfo=None)
|
|
163
|
+
|
|
164
|
+
return naive_datetime
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Columns of a Table built from Arrays.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
import pandas
|
|
12
|
+
|
|
13
|
+
from numdaplot.arrays.array_data import read_stored_values
|
|
14
|
+
from numdaplot.errors.dimension_error import DimensionError
|
|
15
|
+
from numdaplot.errors.empty_list_error import EmptyListError
|
|
16
|
+
from numdaplot.errors.shape_mismatch_error import ShapeMismatchError
|
|
17
|
+
from numdaplot.tables.columns.column_names import require_column_names
|
|
18
|
+
from numdaplot.tables.frames.column import Column
|
|
19
|
+
from numdaplot.tables.frames.column_values import build_column
|
|
20
|
+
from numdaplot.tables.frames.time_range_errors import TimeRangeErrors
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from numdaplot.arrays.array import Array
|
|
24
|
+
|
|
25
|
+
FROM_ARRAYS_OPERATION = "from_arrays"
|
|
26
|
+
COLUMN_ITEM_NAME = "column"
|
|
27
|
+
ONE_DIMENSION = 1
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def build_array_frame(columns: dict[str, Array]) -> pandas.DataFrame:
|
|
31
|
+
"""
|
|
32
|
+
Return the columns of a Table holding the values of one-dimensional Arrays.
|
|
33
|
+
|
|
34
|
+
.. versionadded:: 0.1.0
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
columns
|
|
39
|
+
One Array per column, by column name, all of the same length.
|
|
40
|
+
|
|
41
|
+
Returns
|
|
42
|
+
-------
|
|
43
|
+
pandas.DataFrame
|
|
44
|
+
The columns in the order of the dictionary, rows numbered from 0.
|
|
45
|
+
|
|
46
|
+
Raises
|
|
47
|
+
------
|
|
48
|
+
EmptyListError
|
|
49
|
+
When there is no column.
|
|
50
|
+
InvalidColumnNameError
|
|
51
|
+
When a column name is not a non-empty text.
|
|
52
|
+
DimensionError
|
|
53
|
+
When an Array does not have one dimension.
|
|
54
|
+
ShapeMismatchError
|
|
55
|
+
When the Arrays do not have the same length.
|
|
56
|
+
TimeOverflowError
|
|
57
|
+
When an Array holds a datetime or a duration that nanoseconds cannot hold.
|
|
58
|
+
|
|
59
|
+
Examples
|
|
60
|
+
--------
|
|
61
|
+
>>> import numdaplot as ndp
|
|
62
|
+
>>> from numdaplot.tables.frames.array_frame import build_array_frame
|
|
63
|
+
>>> build_array_frame({"city": ndp.Array.from_list(["Pau"]), "price": ndp.Array.from_list([1.5])})
|
|
64
|
+
city price
|
|
65
|
+
0 Pau 1.5
|
|
66
|
+
"""
|
|
67
|
+
if columns == {}:
|
|
68
|
+
raise EmptyListError(COLUMN_ITEM_NAME)
|
|
69
|
+
|
|
70
|
+
column_names = list(columns)
|
|
71
|
+
require_column_names(column_names)
|
|
72
|
+
built_columns = dict[str, Column]()
|
|
73
|
+
value_counts = list[int]()
|
|
74
|
+
|
|
75
|
+
for column_name, array in columns.items():
|
|
76
|
+
values = read_stored_values(array)
|
|
77
|
+
if values.ndim != ONE_DIMENSION:
|
|
78
|
+
raise DimensionError(FROM_ARRAYS_OPERATION, values.ndim)
|
|
79
|
+
|
|
80
|
+
with TimeRangeErrors(FROM_ARRAYS_OPERATION, column_name):
|
|
81
|
+
column = build_column(values)
|
|
82
|
+
|
|
83
|
+
built_columns[column_name] = column
|
|
84
|
+
value_counts.append(values.size)
|
|
85
|
+
|
|
86
|
+
row_count = value_counts[0]
|
|
87
|
+
|
|
88
|
+
for value_count in value_counts:
|
|
89
|
+
if value_count != row_count:
|
|
90
|
+
raise ShapeMismatchError((row_count,), (value_count,))
|
|
91
|
+
|
|
92
|
+
row_numbers = pandas.RangeIndex(row_count)
|
|
93
|
+
frame = pandas.DataFrame(built_columns, index=row_numbers)
|
|
94
|
+
|
|
95
|
+
return frame
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
r"""
|
|
2
|
+
Cleaning of the column names a Table reads.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from collections.abc import Hashable
|
|
8
|
+
|
|
9
|
+
import pandas
|
|
10
|
+
|
|
11
|
+
from numdaplot.errors.duplicate_column_error import DuplicateColumnError
|
|
12
|
+
from numdaplot.tables.files.column_names import ColumnNames
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def clean_frame_names(frame: pandas.DataFrame, column_names: ColumnNames) -> pandas.DataFrame:
|
|
16
|
+
r"""
|
|
17
|
+
Return a DataFrame read from outside numdaplot, with its column names cleaned when asked.
|
|
18
|
+
|
|
19
|
+
.. versionadded:: 0.1.0
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
frame
|
|
24
|
+
A DataFrame read from a file or given by the user. It is not changed.
|
|
25
|
+
column_names
|
|
26
|
+
``CLEANED`` to remove the spaces, tabs and line breaks at the start and the end of each name, ``KEPT`` to
|
|
27
|
+
keep the names as written.
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
pandas.DataFrame
|
|
32
|
+
The DataFrame with the cleaned names, or the same DataFrame when the names are kept.
|
|
33
|
+
|
|
34
|
+
Raises
|
|
35
|
+
------
|
|
36
|
+
DuplicateColumnError
|
|
37
|
+
When two different names become the same once cleaned.
|
|
38
|
+
|
|
39
|
+
Examples
|
|
40
|
+
--------
|
|
41
|
+
>>> import pandas
|
|
42
|
+
>>> import numdaplot as ndp
|
|
43
|
+
>>> from numdaplot.tables.frames.cleaned_names import clean_frame_names
|
|
44
|
+
>>> frame = pandas.DataFrame({"id_vehicule\n": [1], " speed ": [50]})
|
|
45
|
+
>>> clean_frame_names(frame, ndp.ColumnNames.CLEANED).columns.tolist()
|
|
46
|
+
['id_vehicule', 'speed']
|
|
47
|
+
"""
|
|
48
|
+
if column_names == ColumnNames.KEPT:
|
|
49
|
+
return frame
|
|
50
|
+
|
|
51
|
+
raw_names = list[Hashable](frame.columns)
|
|
52
|
+
cleaned_names = clean_names(raw_names)
|
|
53
|
+
require_distinct_cleaned_names(raw_names, cleaned_names)
|
|
54
|
+
cleaned_frame = frame.copy(deep=False)
|
|
55
|
+
cleaned_frame.columns = pandas.Index(cleaned_names)
|
|
56
|
+
|
|
57
|
+
return cleaned_frame
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def clean_names(names: list[Hashable]) -> list[Hashable]:
|
|
61
|
+
r"""
|
|
62
|
+
Return column names without the spaces, tabs and line breaks at their start and end.
|
|
63
|
+
|
|
64
|
+
A name that is not a text is kept, so that the check of the column names refuses it.
|
|
65
|
+
|
|
66
|
+
.. versionadded:: 0.1.0
|
|
67
|
+
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
names
|
|
71
|
+
The column names.
|
|
72
|
+
|
|
73
|
+
Returns
|
|
74
|
+
-------
|
|
75
|
+
list[Hashable]
|
|
76
|
+
The cleaned names, in the same order.
|
|
77
|
+
|
|
78
|
+
Examples
|
|
79
|
+
--------
|
|
80
|
+
>>> from numdaplot.tables.frames.cleaned_names import clean_names
|
|
81
|
+
>>> clean_names(["id_vehicule\n", " speed", 2024])
|
|
82
|
+
['id_vehicule', 'speed', 2024]
|
|
83
|
+
"""
|
|
84
|
+
cleaned_names = list[Hashable]()
|
|
85
|
+
for name in names:
|
|
86
|
+
cleaned_name = name
|
|
87
|
+
if isinstance(name, str):
|
|
88
|
+
cleaned_name = name.strip()
|
|
89
|
+
|
|
90
|
+
cleaned_names.append(cleaned_name)
|
|
91
|
+
|
|
92
|
+
return cleaned_names
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def require_distinct_cleaned_names(raw_names: list[Hashable], cleaned_names: list[Hashable]) -> None:
|
|
96
|
+
r"""
|
|
97
|
+
Check that two different names do not become the same once cleaned.
|
|
98
|
+
|
|
99
|
+
A name written twice the same way is left to the check of the column names, which names it alone.
|
|
100
|
+
|
|
101
|
+
.. versionadded:: 0.1.0
|
|
102
|
+
|
|
103
|
+
Parameters
|
|
104
|
+
----------
|
|
105
|
+
raw_names
|
|
106
|
+
The column names as written.
|
|
107
|
+
cleaned_names
|
|
108
|
+
The same names once cleaned, in the same order.
|
|
109
|
+
|
|
110
|
+
Raises
|
|
111
|
+
------
|
|
112
|
+
DuplicateColumnError
|
|
113
|
+
At the first cleaned name coming from two different names, with both of them.
|
|
114
|
+
|
|
115
|
+
Examples
|
|
116
|
+
--------
|
|
117
|
+
>>> import numdaplot as ndp
|
|
118
|
+
>>> from numdaplot.tables.frames.cleaned_names import require_distinct_cleaned_names
|
|
119
|
+
>>> try:
|
|
120
|
+
... require_distinct_cleaned_names(["id", "id\n"], ["id", "id"])
|
|
121
|
+
... except ndp.DuplicateColumnError as error:
|
|
122
|
+
... print(error)
|
|
123
|
+
The column names 'id' and 'id\n' both become 'id' once cleaned. Use ColumnNames.KEPT to keep them as written.
|
|
124
|
+
"""
|
|
125
|
+
first_raw_names = dict[Hashable, Hashable]()
|
|
126
|
+
for raw_name, cleaned_name in zip(raw_names, cleaned_names, strict=True):
|
|
127
|
+
first_raw_name = first_raw_names.setdefault(cleaned_name, raw_name)
|
|
128
|
+
if first_raw_name == raw_name:
|
|
129
|
+
continue
|
|
130
|
+
|
|
131
|
+
original_names = [str(first_raw_name), str(raw_name)]
|
|
132
|
+
raise DuplicateColumnError(str(cleaned_name), original_names)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Type of the pandas columns a Table stores.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
import pandas
|
|
10
|
+
|
|
11
|
+
type Column = pandas.Series[Any]
|
|
12
|
+
"""A pandas column of a Table, stored with one of the dtypes given by ``to_pandas_dtype``.
|
|
13
|
+
|
|
14
|
+
.. versionadded:: 0.1.0
|
|
15
|
+
"""
|