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,479 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Arithmetic between dates, datetimes, durations and numbers.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, cast
|
|
8
|
+
|
|
9
|
+
import numpy
|
|
10
|
+
from numpy.typing import NDArray
|
|
11
|
+
|
|
12
|
+
from numdaplot.arrays.conversion.time_text import format_durations
|
|
13
|
+
from numdaplot.arrays.operations.operand import Operand, convert_time_value, find_operand_type
|
|
14
|
+
from numdaplot.arrays.operations.time_bounds import require_nanoseconds_fit
|
|
15
|
+
from numdaplot.arrays.operations.time_result_bounds import require_time_result_fits, widen_large_integers
|
|
16
|
+
from numdaplot.data_types.numpy_mapping import to_numpy_dtype
|
|
17
|
+
from numdaplot.data_types.type import Type
|
|
18
|
+
from numdaplot.data_types.value_family import ValueFamily, find_family
|
|
19
|
+
from numdaplot.errors.incompatible_types_error import IncompatibleTypesError
|
|
20
|
+
from numdaplot.errors.refused_operation_error import RefusedOperationError
|
|
21
|
+
from numdaplot.errors.time_overflow_error import TimeOverflowError
|
|
22
|
+
from numdaplot.errors.value_conversion_error import ValueConversionError
|
|
23
|
+
|
|
24
|
+
TIME_FAMILIES = frozenset({ValueFamily.MOMENT, ValueFamily.DURATION, ValueFamily.TIME})
|
|
25
|
+
# The family of the result of each accepted operation, by function and families of the left and right operands.
|
|
26
|
+
type TimeOperation = tuple[numpy.ufunc, ValueFamily, ValueFamily]
|
|
27
|
+
TIME_RESULTS = dict[TimeOperation, ValueFamily](
|
|
28
|
+
{
|
|
29
|
+
(numpy.add, ValueFamily.MOMENT, ValueFamily.DURATION): ValueFamily.MOMENT,
|
|
30
|
+
(numpy.add, ValueFamily.DURATION, ValueFamily.MOMENT): ValueFamily.MOMENT,
|
|
31
|
+
(numpy.add, ValueFamily.DURATION, ValueFamily.DURATION): ValueFamily.DURATION,
|
|
32
|
+
(numpy.subtract, ValueFamily.MOMENT, ValueFamily.MOMENT): ValueFamily.DURATION,
|
|
33
|
+
(numpy.subtract, ValueFamily.MOMENT, ValueFamily.DURATION): ValueFamily.MOMENT,
|
|
34
|
+
(numpy.subtract, ValueFamily.DURATION, ValueFamily.DURATION): ValueFamily.DURATION,
|
|
35
|
+
(numpy.multiply, ValueFamily.DURATION, ValueFamily.NUMBER): ValueFamily.DURATION,
|
|
36
|
+
(numpy.multiply, ValueFamily.NUMBER, ValueFamily.DURATION): ValueFamily.DURATION,
|
|
37
|
+
(numpy.true_divide, ValueFamily.DURATION, ValueFamily.NUMBER): ValueFamily.DURATION,
|
|
38
|
+
(numpy.add, ValueFamily.TIME, ValueFamily.DURATION): ValueFamily.TIME,
|
|
39
|
+
(numpy.add, ValueFamily.DURATION, ValueFamily.TIME): ValueFamily.TIME,
|
|
40
|
+
(numpy.subtract, ValueFamily.TIME, ValueFamily.DURATION): ValueFamily.TIME,
|
|
41
|
+
(numpy.subtract, ValueFamily.TIME, ValueFamily.TIME): ValueFamily.DURATION,
|
|
42
|
+
(numpy.add, ValueFamily.MOMENT, ValueFamily.TIME): ValueFamily.MOMENT,
|
|
43
|
+
(numpy.add, ValueFamily.TIME, ValueFamily.MOMENT): ValueFamily.MOMENT,
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
DURATION_DIVISION = (numpy.true_divide, ValueFamily.DURATION, ValueFamily.DURATION)
|
|
47
|
+
DURATION_DIVISION_OPERATION = "Dividing a duration by a duration"
|
|
48
|
+
DURATION_DIVISION_ALTERNATIVE = "apply(ndp.DurationIn(unit=...))"
|
|
49
|
+
TIMEDELTA_PRODUCT_OPERATION = "Multiplying numbers by a single duration"
|
|
50
|
+
TIMEDELTA_PRODUCT_ALTERNATIVE = "apply(ndp.ToDuration(unit=...))"
|
|
51
|
+
NANOSECOND_DTYPES = {
|
|
52
|
+
ValueFamily.MOMENT: to_numpy_dtype(Type.DATETIME),
|
|
53
|
+
ValueFamily.DURATION: to_numpy_dtype(Type.DURATION),
|
|
54
|
+
ValueFamily.TIME: to_numpy_dtype(Type.DURATION),
|
|
55
|
+
}
|
|
56
|
+
ONE_DAY = numpy.timedelta64(1, "D")
|
|
57
|
+
NO_DURATION = numpy.timedelta64(0, "ns")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def involves_time(left: Operand, right: Operand) -> bool:
|
|
61
|
+
"""
|
|
62
|
+
Return whether one of two operands holds dates, datetimes or durations.
|
|
63
|
+
|
|
64
|
+
.. versionadded:: 0.1.0
|
|
65
|
+
|
|
66
|
+
Parameters
|
|
67
|
+
----------
|
|
68
|
+
left
|
|
69
|
+
The values of an Array, or a single value.
|
|
70
|
+
right
|
|
71
|
+
The values of an Array, or a single value.
|
|
72
|
+
|
|
73
|
+
Returns
|
|
74
|
+
-------
|
|
75
|
+
bool
|
|
76
|
+
True when at least one side is a date, a datetime or a duration.
|
|
77
|
+
|
|
78
|
+
Examples
|
|
79
|
+
--------
|
|
80
|
+
>>> from datetime import timedelta
|
|
81
|
+
>>> import numpy
|
|
82
|
+
>>> from numdaplot.arrays.operations.time_arithmetic import involves_time
|
|
83
|
+
>>> involves_time(numpy.array([1, 2]), timedelta(days=1))
|
|
84
|
+
True
|
|
85
|
+
"""
|
|
86
|
+
left_type = find_operand_type(left)
|
|
87
|
+
right_type = find_operand_type(right)
|
|
88
|
+
left_family = find_family(left_type)
|
|
89
|
+
right_family = find_family(right_type)
|
|
90
|
+
has_time = left_family in TIME_FAMILIES or right_family in TIME_FAMILIES
|
|
91
|
+
|
|
92
|
+
return has_time
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def combine_time_values(left: Operand, right: Operand, function: numpy.ufunc, symbol: str) -> NDArray[Any]:
|
|
96
|
+
"""
|
|
97
|
+
Return the result of an arithmetic function between dates, datetimes, durations and numbers.
|
|
98
|
+
|
|
99
|
+
Dates and datetimes give durations when subtracted; a duration added to or subtracted from a date gives
|
|
100
|
+
a date, and from a datetime a datetime; durations add, subtract, and multiply or divide by numbers.
|
|
101
|
+
A date counts as midnight next to a datetime. Times of day give durations when subtracted, move by a
|
|
102
|
+
duration within the same day, and give a datetime when added to a date.
|
|
103
|
+
|
|
104
|
+
.. versionadded:: 0.1.0
|
|
105
|
+
|
|
106
|
+
Parameters
|
|
107
|
+
----------
|
|
108
|
+
left
|
|
109
|
+
The values of an Array, or a single value.
|
|
110
|
+
right
|
|
111
|
+
The values of an Array, or a single value. At least one side holds dates, datetimes or durations.
|
|
112
|
+
function
|
|
113
|
+
The numpy function, such as ``numpy.add``.
|
|
114
|
+
symbol
|
|
115
|
+
The operator shown in error messages, such as ``"+"``.
|
|
116
|
+
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
NDArray
|
|
120
|
+
Dates, datetimes in nanoseconds or durations in nanoseconds.
|
|
121
|
+
|
|
122
|
+
Raises
|
|
123
|
+
------
|
|
124
|
+
RefusedOperationError
|
|
125
|
+
When a duration is divided by a duration, or numbers are multiplied by a single duration.
|
|
126
|
+
ValueConversionError
|
|
127
|
+
When a duration added to or subtracted from dates is not a whole number of days.
|
|
128
|
+
IncompatibleTypesError
|
|
129
|
+
When the operation does not apply to these types, such as a date plus a number, or a datetime plus a time of
|
|
130
|
+
day.
|
|
131
|
+
TimeOverflowError
|
|
132
|
+
When an operand or a result is outside the range of nanoseconds, about 1677 to 2262 for dates and
|
|
133
|
+
datetimes, and about 292 years for durations, or a time of day moves past midnight.
|
|
134
|
+
|
|
135
|
+
Examples
|
|
136
|
+
--------
|
|
137
|
+
>>> from datetime import timedelta
|
|
138
|
+
>>> import numpy
|
|
139
|
+
>>> from numdaplot.arrays.operations.time_arithmetic import combine_time_values
|
|
140
|
+
>>> combine_time_values(numpy.array(["2026-01-31"], dtype="datetime64[D]"), timedelta(days=1), numpy.add, "+")
|
|
141
|
+
array(['2026-02-01'], dtype='datetime64[D]')
|
|
142
|
+
"""
|
|
143
|
+
left_type = find_operand_type(left)
|
|
144
|
+
right_type = find_operand_type(right)
|
|
145
|
+
left_family = find_family(left_type)
|
|
146
|
+
right_family = find_family(right_type)
|
|
147
|
+
operation_key = (function, left_family, right_family)
|
|
148
|
+
require_time_operation(left, right, operation_key)
|
|
149
|
+
if operation_key not in TIME_RESULTS:
|
|
150
|
+
raise IncompatibleTypesError(symbol, [left_type.name, right_type.name])
|
|
151
|
+
|
|
152
|
+
require_date_next_to_time(left_type, right_type, symbol)
|
|
153
|
+
result_family = TIME_RESULTS[operation_key]
|
|
154
|
+
shifts_date = Type.DATE in (left_type, right_type) and ValueFamily.DURATION in (left_family, right_family)
|
|
155
|
+
keeps_date = shifts_date and result_family == ValueFamily.MOMENT
|
|
156
|
+
result_type = find_time_result_type(result_family, keeps_date)
|
|
157
|
+
operands = [left, right]
|
|
158
|
+
combined_values = combine_nanoseconds(operands, function, result_type, symbol)
|
|
159
|
+
if result_type == Type.TIME:
|
|
160
|
+
times = store_time_result(combined_values, symbol)
|
|
161
|
+
return times
|
|
162
|
+
|
|
163
|
+
if not keeps_date:
|
|
164
|
+
return combined_values
|
|
165
|
+
|
|
166
|
+
date_shift = to_nanoseconds(right, right_family)
|
|
167
|
+
if left_family == ValueFamily.DURATION:
|
|
168
|
+
date_shift = to_nanoseconds(left, left_family)
|
|
169
|
+
|
|
170
|
+
require_whole_days(date_shift)
|
|
171
|
+
date_dtype = to_numpy_dtype(Type.DATE)
|
|
172
|
+
shifted_dates = combined_values.astype(date_dtype)
|
|
173
|
+
|
|
174
|
+
return shifted_dates
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def combine_nanoseconds(operands: list[Operand], function: numpy.ufunc, result_type: Type, symbol: str) -> NDArray[Any]:
|
|
178
|
+
"""
|
|
179
|
+
Return an arithmetic function applied to operands counted in nanoseconds, refusing results that do not fit.
|
|
180
|
+
|
|
181
|
+
.. versionadded:: 0.1.0
|
|
182
|
+
|
|
183
|
+
Parameters
|
|
184
|
+
----------
|
|
185
|
+
operands
|
|
186
|
+
The left and the right operand, values of Arrays or single values.
|
|
187
|
+
function
|
|
188
|
+
The numpy function, such as ``numpy.add``.
|
|
189
|
+
result_type
|
|
190
|
+
The type of the result, named by the errors.
|
|
191
|
+
symbol
|
|
192
|
+
The operator shown in error messages, such as ``"+"``.
|
|
193
|
+
|
|
194
|
+
Returns
|
|
195
|
+
-------
|
|
196
|
+
NDArray
|
|
197
|
+
The result, dates and datetimes in ``datetime64[ns]`` and durations in ``timedelta64[ns]``.
|
|
198
|
+
|
|
199
|
+
Raises
|
|
200
|
+
------
|
|
201
|
+
TimeOverflowError
|
|
202
|
+
When an operand or the result is outside the range of nanoseconds.
|
|
203
|
+
|
|
204
|
+
Examples
|
|
205
|
+
--------
|
|
206
|
+
>>> from datetime import timedelta
|
|
207
|
+
>>> import numpy
|
|
208
|
+
>>> import numdaplot as ndp
|
|
209
|
+
>>> from numdaplot.arrays.operations.time_arithmetic import combine_nanoseconds
|
|
210
|
+
>>> durations = numpy.array([1], dtype="timedelta64[s]")
|
|
211
|
+
>>> combine_nanoseconds([durations, timedelta(seconds=1)], numpy.add, ndp.Type.DURATION, "+")
|
|
212
|
+
array([2000000000], dtype='timedelta64[ns]')
|
|
213
|
+
"""
|
|
214
|
+
left, right = operands
|
|
215
|
+
left_type = find_operand_type(left)
|
|
216
|
+
right_type = find_operand_type(right)
|
|
217
|
+
require_nanoseconds_fit(left, left_type, symbol)
|
|
218
|
+
require_nanoseconds_fit(right, right_type, symbol)
|
|
219
|
+
left_family = find_family(left_type)
|
|
220
|
+
right_family = find_family(right_type)
|
|
221
|
+
left_values = to_nanoseconds(left, left_family)
|
|
222
|
+
right_values = to_nanoseconds(right, right_family)
|
|
223
|
+
# A time of day moved by a duration is first computed as a duration, then checked against midnight.
|
|
224
|
+
fitted_type = Type.DURATION if result_type == Type.TIME else result_type
|
|
225
|
+
try:
|
|
226
|
+
left_numbers = widen_large_integers(left_values)
|
|
227
|
+
right_numbers = widen_large_integers(right_values)
|
|
228
|
+
number_operands = [left_numbers, right_numbers]
|
|
229
|
+
require_time_result_fits(number_operands, function, fitted_type, symbol)
|
|
230
|
+
combined_values = function(left_numbers, right_numbers)
|
|
231
|
+
except OverflowError as error:
|
|
232
|
+
raise TimeOverflowError(symbol, fitted_type.name) from error
|
|
233
|
+
|
|
234
|
+
return combined_values
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def store_time_result(durations: NDArray[Any], symbol: str) -> NDArray[numpy.timedelta64]:
|
|
238
|
+
"""
|
|
239
|
+
Return times of day computed as durations since midnight, refusing those past midnight.
|
|
240
|
+
|
|
241
|
+
.. versionadded:: 0.1.0
|
|
242
|
+
|
|
243
|
+
Parameters
|
|
244
|
+
----------
|
|
245
|
+
durations
|
|
246
|
+
The times since midnight in ``timedelta64[ns]``, NaT where missing.
|
|
247
|
+
symbol
|
|
248
|
+
The operator shown in error messages, such as ``"+"``.
|
|
249
|
+
|
|
250
|
+
Returns
|
|
251
|
+
-------
|
|
252
|
+
NDArray[numpy.timedelta64]
|
|
253
|
+
The times of day in ``timedelta64[us]``.
|
|
254
|
+
|
|
255
|
+
Raises
|
|
256
|
+
------
|
|
257
|
+
TimeOverflowError
|
|
258
|
+
When a time is before midnight or from the next midnight on.
|
|
259
|
+
|
|
260
|
+
Examples
|
|
261
|
+
--------
|
|
262
|
+
>>> import numpy
|
|
263
|
+
>>> from numdaplot.arrays.operations.time_arithmetic import store_time_result
|
|
264
|
+
>>> store_time_result(numpy.array([3600000000000], dtype="timedelta64[ns]"), "+")
|
|
265
|
+
array([3600000000], dtype='timedelta64[us]')
|
|
266
|
+
"""
|
|
267
|
+
is_missing = numpy.isnat(durations)
|
|
268
|
+
is_before_midnight = durations < NO_DURATION
|
|
269
|
+
is_next_day = durations >= ONE_DAY
|
|
270
|
+
is_outside_day = (is_before_midnight | is_next_day) & ~is_missing
|
|
271
|
+
has_outside_day = bool(is_outside_day.any())
|
|
272
|
+
if has_outside_day:
|
|
273
|
+
raise TimeOverflowError(symbol, Type.TIME.name)
|
|
274
|
+
|
|
275
|
+
time_dtype = to_numpy_dtype(Type.TIME)
|
|
276
|
+
times = durations.astype(time_dtype)
|
|
277
|
+
|
|
278
|
+
return times
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def require_date_next_to_time(left_type: Type, right_type: Type, symbol: str) -> None:
|
|
282
|
+
"""
|
|
283
|
+
Check that a time of day is only added to dates, never to datetimes, which already have a time.
|
|
284
|
+
|
|
285
|
+
.. versionadded:: 0.1.0
|
|
286
|
+
|
|
287
|
+
Parameters
|
|
288
|
+
----------
|
|
289
|
+
left_type
|
|
290
|
+
The type of the left operand.
|
|
291
|
+
right_type
|
|
292
|
+
The type of the right operand.
|
|
293
|
+
symbol
|
|
294
|
+
The operator shown in error messages, such as ``"+"``.
|
|
295
|
+
|
|
296
|
+
Raises
|
|
297
|
+
------
|
|
298
|
+
IncompatibleTypesError
|
|
299
|
+
When a time of day is combined with datetimes.
|
|
300
|
+
|
|
301
|
+
Examples
|
|
302
|
+
--------
|
|
303
|
+
>>> import numdaplot as ndp
|
|
304
|
+
>>> from numdaplot.arrays.operations.time_arithmetic import require_date_next_to_time
|
|
305
|
+
>>> try:
|
|
306
|
+
... require_date_next_to_time(ndp.Type.DATETIME, ndp.Type.TIME, "+")
|
|
307
|
+
... except ndp.IncompatibleTypesError as error:
|
|
308
|
+
... print(error)
|
|
309
|
+
Cannot apply + to DATETIME and TIME.
|
|
310
|
+
"""
|
|
311
|
+
operand_types = (left_type, right_type)
|
|
312
|
+
combines_datetime_with_time = Type.TIME in operand_types and Type.DATETIME in operand_types
|
|
313
|
+
if combines_datetime_with_time:
|
|
314
|
+
raise IncompatibleTypesError(symbol, [left_type.name, right_type.name])
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def find_time_result_type(result_family: ValueFamily, keeps_date: bool) -> Type:
|
|
318
|
+
"""
|
|
319
|
+
Return the type of the result of an accepted operation on times.
|
|
320
|
+
|
|
321
|
+
.. versionadded:: 0.1.0
|
|
322
|
+
|
|
323
|
+
Parameters
|
|
324
|
+
----------
|
|
325
|
+
result_family
|
|
326
|
+
The family of the result, ``MOMENT`` or ``DURATION``.
|
|
327
|
+
keeps_date
|
|
328
|
+
Whether the result stays a date.
|
|
329
|
+
|
|
330
|
+
Returns
|
|
331
|
+
-------
|
|
332
|
+
Type
|
|
333
|
+
``DURATION``, ``TIME``, ``DATE`` or ``DATETIME``.
|
|
334
|
+
|
|
335
|
+
Examples
|
|
336
|
+
--------
|
|
337
|
+
>>> from numdaplot.arrays.operations.time_arithmetic import find_time_result_type
|
|
338
|
+
>>> from numdaplot.data_types.value_family import ValueFamily
|
|
339
|
+
>>> find_time_result_type(ValueFamily.MOMENT, True)
|
|
340
|
+
<Type.DATE: 14>
|
|
341
|
+
"""
|
|
342
|
+
if result_family == ValueFamily.DURATION:
|
|
343
|
+
return Type.DURATION
|
|
344
|
+
|
|
345
|
+
if result_family == ValueFamily.TIME:
|
|
346
|
+
return Type.TIME
|
|
347
|
+
|
|
348
|
+
if keeps_date:
|
|
349
|
+
return Type.DATE
|
|
350
|
+
|
|
351
|
+
return Type.DATETIME
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def require_time_operation(left: Operand, right: Operand, operation_key: TimeOperation) -> None:
|
|
355
|
+
"""
|
|
356
|
+
Check that an operation is not one of the duration operations written another way in numdaplot.
|
|
357
|
+
|
|
358
|
+
.. versionadded:: 0.1.0
|
|
359
|
+
|
|
360
|
+
Parameters
|
|
361
|
+
----------
|
|
362
|
+
left
|
|
363
|
+
The values of an Array, or a single value.
|
|
364
|
+
right
|
|
365
|
+
The values of an Array, or a single value.
|
|
366
|
+
operation_key
|
|
367
|
+
The numpy function, then the families of the left and right operands.
|
|
368
|
+
|
|
369
|
+
Raises
|
|
370
|
+
------
|
|
371
|
+
RefusedOperationError
|
|
372
|
+
When a duration is divided by a duration, which ``DurationIn`` does, or numbers are multiplied
|
|
373
|
+
by a single duration, which ``ToDuration`` does.
|
|
374
|
+
|
|
375
|
+
Examples
|
|
376
|
+
--------
|
|
377
|
+
>>> from datetime import timedelta
|
|
378
|
+
>>> import numpy
|
|
379
|
+
>>> import numdaplot as ndp
|
|
380
|
+
>>> from numdaplot.arrays.operations.time_arithmetic import require_time_operation
|
|
381
|
+
>>> from numdaplot.data_types.value_family import ValueFamily
|
|
382
|
+
>>> key = (numpy.multiply, ValueFamily.NUMBER, ValueFamily.DURATION)
|
|
383
|
+
>>> try:
|
|
384
|
+
... require_time_operation(numpy.array([3]), timedelta(days=1), key)
|
|
385
|
+
... except ndp.RefusedOperationError as error:
|
|
386
|
+
... print(error)
|
|
387
|
+
Multiplying numbers by a single duration is not available, use apply(ndp.ToDuration(unit=...)) instead.
|
|
388
|
+
"""
|
|
389
|
+
if operation_key == DURATION_DIVISION:
|
|
390
|
+
raise RefusedOperationError(DURATION_DIVISION_OPERATION, DURATION_DIVISION_ALTERNATIVE)
|
|
391
|
+
|
|
392
|
+
function, left_family, right_family = operation_key
|
|
393
|
+
if function != numpy.multiply:
|
|
394
|
+
return
|
|
395
|
+
|
|
396
|
+
left_is_single_duration = left_family == ValueFamily.DURATION and not isinstance(left, numpy.ndarray)
|
|
397
|
+
right_is_single_duration = right_family == ValueFamily.DURATION and not isinstance(right, numpy.ndarray)
|
|
398
|
+
multiplies_single_duration = left_is_single_duration or right_is_single_duration
|
|
399
|
+
if multiplies_single_duration:
|
|
400
|
+
raise RefusedOperationError(TIMEDELTA_PRODUCT_OPERATION, TIMEDELTA_PRODUCT_ALTERNATIVE)
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
def to_nanoseconds(operand: Operand, family: ValueFamily) -> Any:
|
|
404
|
+
"""
|
|
405
|
+
Return an operand with its dates, datetimes or durations counted in nanoseconds.
|
|
406
|
+
|
|
407
|
+
.. versionadded:: 0.1.0
|
|
408
|
+
|
|
409
|
+
Parameters
|
|
410
|
+
----------
|
|
411
|
+
operand
|
|
412
|
+
The values of an Array, or a single value.
|
|
413
|
+
family
|
|
414
|
+
The family of the operand.
|
|
415
|
+
|
|
416
|
+
Returns
|
|
417
|
+
-------
|
|
418
|
+
Any
|
|
419
|
+
Datetimes or durations in nanoseconds, or the operand itself when it holds numbers.
|
|
420
|
+
|
|
421
|
+
Examples
|
|
422
|
+
--------
|
|
423
|
+
>>> from datetime import date
|
|
424
|
+
>>> from numdaplot.arrays.operations.time_arithmetic import to_nanoseconds
|
|
425
|
+
>>> from numdaplot.data_types.value_family import ValueFamily
|
|
426
|
+
>>> to_nanoseconds(date(2026, 1, 31), ValueFamily.MOMENT)
|
|
427
|
+
np.datetime64('2026-01-31T00:00:00.000000000')
|
|
428
|
+
"""
|
|
429
|
+
if family not in NANOSECOND_DTYPES:
|
|
430
|
+
return operand
|
|
431
|
+
|
|
432
|
+
numpy_operand = cast(Any, operand)
|
|
433
|
+
if not isinstance(operand, numpy.ndarray):
|
|
434
|
+
numpy_operand = convert_time_value(operand)
|
|
435
|
+
|
|
436
|
+
nanosecond_dtype = NANOSECOND_DTYPES[family]
|
|
437
|
+
nanosecond_operand = numpy_operand.astype(nanosecond_dtype)
|
|
438
|
+
|
|
439
|
+
return nanosecond_operand
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
def require_whole_days(durations: NDArray[numpy.timedelta64] | numpy.timedelta64) -> None:
|
|
443
|
+
"""
|
|
444
|
+
Check that durations added to or subtracted from dates are whole numbers of days.
|
|
445
|
+
|
|
446
|
+
.. versionadded:: 0.1.0
|
|
447
|
+
|
|
448
|
+
Parameters
|
|
449
|
+
----------
|
|
450
|
+
durations
|
|
451
|
+
Durations in nanoseconds, an array or a single value.
|
|
452
|
+
|
|
453
|
+
Raises
|
|
454
|
+
------
|
|
455
|
+
ValueConversionError
|
|
456
|
+
When a duration is not a whole number of days, citing the first one.
|
|
457
|
+
|
|
458
|
+
Examples
|
|
459
|
+
--------
|
|
460
|
+
>>> import numpy
|
|
461
|
+
>>> import numdaplot as ndp
|
|
462
|
+
>>> from numdaplot.arrays.operations.time_arithmetic import require_whole_days
|
|
463
|
+
>>> try:
|
|
464
|
+
... require_whole_days(numpy.array([36], dtype="timedelta64[h]").astype("timedelta64[ns]"))
|
|
465
|
+
... except ndp.ValueConversionError as error:
|
|
466
|
+
... print(error)
|
|
467
|
+
Cannot store the DURATION value '1 days 12:00:00' as DATE without losing information.
|
|
468
|
+
"""
|
|
469
|
+
duration_values = numpy.atleast_1d(durations)
|
|
470
|
+
present_durations = duration_values[~numpy.isnat(duration_values)]
|
|
471
|
+
remainders = present_durations % ONE_DAY
|
|
472
|
+
partial_days = present_durations[remainders != NO_DURATION]
|
|
473
|
+
partial_count = len(partial_days)
|
|
474
|
+
if partial_count == 0:
|
|
475
|
+
return
|
|
476
|
+
|
|
477
|
+
partial_texts = format_durations(partial_days)
|
|
478
|
+
first_partial_text = str(partial_texts[0])
|
|
479
|
+
raise ValueConversionError(Type.DURATION.name, Type.DATE.name, first_partial_text)
|