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,313 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Conversion of Table columns to and from times of day.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, cast
|
|
8
|
+
|
|
9
|
+
import numpy
|
|
10
|
+
import pandas
|
|
11
|
+
|
|
12
|
+
from numdaplot.data_types.time_of_day import TIME_DTYPE
|
|
13
|
+
from numdaplot.data_types.type import Type
|
|
14
|
+
from numdaplot.dates.custom_date_format import CustomDateFormat
|
|
15
|
+
from numdaplot.errors.value_conversion_error import ValueConversionError
|
|
16
|
+
from numdaplot.tables.frames.column import Column
|
|
17
|
+
from numdaplot.tables.frames.column_values import find_column_missing, find_column_type
|
|
18
|
+
from numdaplot.tables.frames.frame_normalization import convert_to_type
|
|
19
|
+
from numdaplot.tables.frames.time_columns import write_time_texts_column
|
|
20
|
+
from numdaplot.tables.frames.time_zones import find_column_time_zone
|
|
21
|
+
|
|
22
|
+
DEFAULT_TIME_FORMAT_NAME = "HH:MM:SS"
|
|
23
|
+
CLOCK_PATTERN = r"^(?P<hour>\d{1,2}):(?P<minute>\d{2})(?::(?P<second>\d{2})(?:\.(?P<fraction>\d{1,6}))?)?$"
|
|
24
|
+
CLOCK_PARTS = ["hour", "minute", "second"]
|
|
25
|
+
CLOCK_LIMITS = {"hour": 24, "minute": 60, "second": 60}
|
|
26
|
+
FRACTION_PART = "fraction"
|
|
27
|
+
FRACTION_DIGITS = 6
|
|
28
|
+
FRACTION_PADDING = "0"
|
|
29
|
+
MISSING_PART = "0"
|
|
30
|
+
MICROSECONDS_PER_UNIT = {"hour": 3_600_000_000, "minute": 60_000_000, "second": 1_000_000}
|
|
31
|
+
COLUMN_AXIS = "columns"
|
|
32
|
+
REFERENCE_DAY = pandas.Timestamp("1900-01-01")
|
|
33
|
+
MICROSECOND_UNIT = "us"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def parse_times(column: Column, time_format: CustomDateFormat | None) -> Column:
|
|
37
|
+
"""
|
|
38
|
+
Return a text or category column read as times of day.
|
|
39
|
+
|
|
40
|
+
The spaces around each text are removed. Without format, ``HH:MM``, ``HH:MM:SS`` and ``HH:MM:SS.ffffff`` are
|
|
41
|
+
read, the hour having one or two digits.
|
|
42
|
+
|
|
43
|
+
.. versionadded:: 0.1.0
|
|
44
|
+
|
|
45
|
+
Parameters
|
|
46
|
+
----------
|
|
47
|
+
column
|
|
48
|
+
A text or category column.
|
|
49
|
+
time_format
|
|
50
|
+
A pattern of a time without date, such as ``"%H%M"``, or None for the default reading.
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
-------
|
|
54
|
+
Column
|
|
55
|
+
A ``TIME`` column, missing values staying missing.
|
|
56
|
+
|
|
57
|
+
Raises
|
|
58
|
+
------
|
|
59
|
+
ValueConversionError
|
|
60
|
+
At the first text that is not a time in the format.
|
|
61
|
+
|
|
62
|
+
Examples
|
|
63
|
+
--------
|
|
64
|
+
>>> import pandas
|
|
65
|
+
>>> import numdaplot as ndp
|
|
66
|
+
>>> from numdaplot.tables.columns.time_conversion import parse_times
|
|
67
|
+
>>> parse_times(pandas.Series(["15:35", " 8:05:30.5", None], dtype="string"), None).tolist()
|
|
68
|
+
[Timedelta('0 days 15:35:00'), Timedelta('0 days 08:05:30.500000'), NaT]
|
|
69
|
+
>>> parse_times(pandas.Series(["1535"], dtype="string"), ndp.CustomDateFormat("%H%M")).tolist()
|
|
70
|
+
[Timedelta('0 days 15:35:00')]
|
|
71
|
+
"""
|
|
72
|
+
source_type = find_column_type(column)
|
|
73
|
+
text_column = convert_to_type(column, Type.TEXT)
|
|
74
|
+
stripped_texts = text_column.str.strip()
|
|
75
|
+
times = read_times(stripped_texts, time_format)
|
|
76
|
+
missing = find_column_missing(column)
|
|
77
|
+
unread_times = times.isna()
|
|
78
|
+
unread = unread_times.to_numpy(dtype=numpy.bool_)
|
|
79
|
+
rejected = unread & ~missing
|
|
80
|
+
has_rejected = bool(rejected.any())
|
|
81
|
+
if has_rejected:
|
|
82
|
+
rejected_texts = text_column[rejected]
|
|
83
|
+
first_rejected_text = rejected_texts.iloc[0]
|
|
84
|
+
format_name = find_time_format_name(time_format)
|
|
85
|
+
raise ValueConversionError(source_type.name, Type.TIME.name, first_rejected_text, format_name)
|
|
86
|
+
|
|
87
|
+
return times
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def read_times(texts: Column, time_format: CustomDateFormat | None) -> Column:
|
|
91
|
+
"""
|
|
92
|
+
Return texts read as times of day, NaT where a text is not a time in the format.
|
|
93
|
+
|
|
94
|
+
.. versionadded:: 0.1.0
|
|
95
|
+
|
|
96
|
+
Parameters
|
|
97
|
+
----------
|
|
98
|
+
texts
|
|
99
|
+
A column of texts without spaces around them.
|
|
100
|
+
time_format
|
|
101
|
+
A pattern of a time without date, or None for the default reading.
|
|
102
|
+
|
|
103
|
+
Returns
|
|
104
|
+
-------
|
|
105
|
+
Column
|
|
106
|
+
A column in ``timedelta64[us]``.
|
|
107
|
+
|
|
108
|
+
Examples
|
|
109
|
+
--------
|
|
110
|
+
>>> import pandas
|
|
111
|
+
>>> from numdaplot.tables.columns.time_conversion import read_times
|
|
112
|
+
>>> read_times(pandas.Series(["24:00", "23:59"], dtype="string"), None).tolist()
|
|
113
|
+
[NaT, Timedelta('0 days 23:59:00')]
|
|
114
|
+
"""
|
|
115
|
+
if time_format is None:
|
|
116
|
+
default_times = read_clock_texts(texts)
|
|
117
|
+
return default_times
|
|
118
|
+
|
|
119
|
+
moments = pandas.to_datetime(texts, format=time_format.pattern, errors="coerce")
|
|
120
|
+
moment_column = cast(Column, moments)
|
|
121
|
+
custom_times = keep_time_of_day(moment_column)
|
|
122
|
+
|
|
123
|
+
return custom_times
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def read_clock_texts(texts: Column) -> Column:
|
|
127
|
+
"""
|
|
128
|
+
Return texts written as ``HH:MM``, ``HH:MM:SS`` or ``HH:MM:SS.ffffff`` read as times of day.
|
|
129
|
+
|
|
130
|
+
.. versionadded:: 0.1.0
|
|
131
|
+
|
|
132
|
+
Parameters
|
|
133
|
+
----------
|
|
134
|
+
texts
|
|
135
|
+
A column of texts without spaces around them.
|
|
136
|
+
|
|
137
|
+
Returns
|
|
138
|
+
-------
|
|
139
|
+
Column
|
|
140
|
+
A column in ``timedelta64[us]``, NaT where a text is not such a time, or has an hour from 24, a minute or a
|
|
141
|
+
second from 60.
|
|
142
|
+
|
|
143
|
+
Examples
|
|
144
|
+
--------
|
|
145
|
+
>>> import pandas
|
|
146
|
+
>>> from numdaplot.tables.columns.time_conversion import read_clock_texts
|
|
147
|
+
>>> read_clock_texts(pandas.Series(["9:07", "12:60", "noon"], dtype="string")).tolist()
|
|
148
|
+
[Timedelta('0 days 09:07:00'), NaT, NaT]
|
|
149
|
+
"""
|
|
150
|
+
# Some versions of the pandas stubs leave the columns of the extracted parts unknown.
|
|
151
|
+
extracted_parts = cast(Any, texts.str.extract(CLOCK_PATTERN))
|
|
152
|
+
hours = extracted_parts[CLOCK_PARTS[0]]
|
|
153
|
+
is_clock = hours.notna()
|
|
154
|
+
clock_parts = extracted_parts[CLOCK_PARTS].fillna(MISSING_PART)
|
|
155
|
+
number_parts = clock_parts.where(is_clock).astype(numpy.float64)
|
|
156
|
+
clock_limits = pandas.Series(CLOCK_LIMITS)
|
|
157
|
+
out_of_range = number_parts.ge(clock_limits)
|
|
158
|
+
is_impossible = out_of_range.any(axis=COLUMN_AXIS)
|
|
159
|
+
microsecond_weights = pandas.Series(MICROSECONDS_PER_UNIT)
|
|
160
|
+
weighted_parts = number_parts.mul(microsecond_weights)
|
|
161
|
+
whole_microseconds = weighted_parts.sum(axis=COLUMN_AXIS, min_count=len(CLOCK_PARTS))
|
|
162
|
+
fractions = read_fraction_microseconds(extracted_parts[FRACTION_PART])
|
|
163
|
+
microseconds = whole_microseconds + fractions
|
|
164
|
+
possible_microseconds = microseconds.mask(is_impossible)
|
|
165
|
+
# Some versions of the pandas stubs leave the types of to_timedelta, fillna and mask partly unknown.
|
|
166
|
+
time_pandas = cast(Any, pandas)
|
|
167
|
+
raw_times = time_pandas.to_timedelta(possible_microseconds, unit=MICROSECOND_UNIT)
|
|
168
|
+
times = cast(Column, raw_times)
|
|
169
|
+
time_column = times.astype(TIME_DTYPE)
|
|
170
|
+
|
|
171
|
+
return time_column
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def read_fraction_microseconds(fractions: Column) -> Column:
|
|
175
|
+
"""
|
|
176
|
+
Return the decimal part of seconds, written with 1 to 6 digits, as microseconds.
|
|
177
|
+
|
|
178
|
+
.. versionadded:: 0.1.0
|
|
179
|
+
|
|
180
|
+
Parameters
|
|
181
|
+
----------
|
|
182
|
+
fractions
|
|
183
|
+
The digits after the decimal point, missing when there are none.
|
|
184
|
+
|
|
185
|
+
Returns
|
|
186
|
+
-------
|
|
187
|
+
Column
|
|
188
|
+
The microseconds, 0 where there are no digits.
|
|
189
|
+
|
|
190
|
+
Examples
|
|
191
|
+
--------
|
|
192
|
+
>>> import pandas
|
|
193
|
+
>>> from numdaplot.tables.columns.time_conversion import read_fraction_microseconds
|
|
194
|
+
>>> read_fraction_microseconds(pandas.Series(["5", "000250", None], dtype=object)).tolist()
|
|
195
|
+
[500000.0, 250.0, 0.0]
|
|
196
|
+
"""
|
|
197
|
+
# Some versions of the pandas stubs leave the types of fillna partly unknown.
|
|
198
|
+
fraction_column = cast(Any, fractions)
|
|
199
|
+
filled_fractions = cast(Column, fraction_column.fillna(MISSING_PART))
|
|
200
|
+
text_fractions = filled_fractions.astype(str)
|
|
201
|
+
padded_fractions = text_fractions.str.ljust(FRACTION_DIGITS, FRACTION_PADDING)
|
|
202
|
+
microseconds = padded_fractions.astype(numpy.float64)
|
|
203
|
+
|
|
204
|
+
return microseconds
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def keep_time_of_day(moments: Column) -> Column:
|
|
208
|
+
"""
|
|
209
|
+
Return the time of day of datetimes, the local time for datetimes with a time zone.
|
|
210
|
+
|
|
211
|
+
.. versionadded:: 0.1.0
|
|
212
|
+
|
|
213
|
+
Parameters
|
|
214
|
+
----------
|
|
215
|
+
moments
|
|
216
|
+
A column of datetimes, NaT where missing.
|
|
217
|
+
|
|
218
|
+
Returns
|
|
219
|
+
-------
|
|
220
|
+
Column
|
|
221
|
+
A column in ``timedelta64[us]``: the time since the midnight of each day.
|
|
222
|
+
|
|
223
|
+
Examples
|
|
224
|
+
--------
|
|
225
|
+
>>> import pandas
|
|
226
|
+
>>> from numdaplot.tables.columns.time_conversion import keep_time_of_day
|
|
227
|
+
>>> keep_time_of_day(pandas.Series(pandas.to_datetime(["2026-03-14 15:35"]))).tolist()
|
|
228
|
+
[Timedelta('0 days 15:35:00')]
|
|
229
|
+
"""
|
|
230
|
+
local_moments = moments
|
|
231
|
+
time_zone = find_column_time_zone(moments)
|
|
232
|
+
if time_zone is not None:
|
|
233
|
+
local_moments = moments.dt.tz_localize(None)
|
|
234
|
+
|
|
235
|
+
midnights = local_moments.dt.normalize()
|
|
236
|
+
since_midnight = local_moments - midnights
|
|
237
|
+
times = since_midnight.astype(TIME_DTYPE)
|
|
238
|
+
|
|
239
|
+
return times
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def write_times(column: Column, time_format: CustomDateFormat | None) -> Column:
|
|
243
|
+
"""
|
|
244
|
+
Return a column of times of day written as texts.
|
|
245
|
+
|
|
246
|
+
.. versionadded:: 0.1.0
|
|
247
|
+
|
|
248
|
+
Parameters
|
|
249
|
+
----------
|
|
250
|
+
column
|
|
251
|
+
A ``TIME`` column.
|
|
252
|
+
time_format
|
|
253
|
+
A pattern of a time without date, such as ``"%Hh%M"``, or None for ``15:35:00``, with microseconds only
|
|
254
|
+
when there are some.
|
|
255
|
+
|
|
256
|
+
Returns
|
|
257
|
+
-------
|
|
258
|
+
Column
|
|
259
|
+
A ``TEXT`` column, missing values staying missing.
|
|
260
|
+
|
|
261
|
+
Examples
|
|
262
|
+
--------
|
|
263
|
+
>>> import numpy
|
|
264
|
+
>>> import pandas
|
|
265
|
+
>>> import numdaplot as ndp
|
|
266
|
+
>>> from numdaplot.tables.columns.time_conversion import write_times
|
|
267
|
+
>>> times = pandas.Series(numpy.array([56100000000, "NaT"], dtype="timedelta64[us]"))
|
|
268
|
+
>>> write_times(times, None).tolist()
|
|
269
|
+
['15:35:00', <NA>]
|
|
270
|
+
>>> write_times(times, ndp.CustomDateFormat("%Hh%M")).tolist()
|
|
271
|
+
['15h35', <NA>]
|
|
272
|
+
"""
|
|
273
|
+
missing = column.isna()
|
|
274
|
+
if time_format is None:
|
|
275
|
+
# Some versions of the pandas stubs leave the types of mask partly unknown.
|
|
276
|
+
default_texts = cast(Any, write_time_texts_column(column))
|
|
277
|
+
present_texts = cast(Column, default_texts.mask(missing))
|
|
278
|
+
default_column = convert_to_type(present_texts, Type.TEXT)
|
|
279
|
+
return default_column
|
|
280
|
+
|
|
281
|
+
moments = REFERENCE_DAY + column
|
|
282
|
+
custom_texts = moments.dt.strftime(time_format.pattern)
|
|
283
|
+
custom_column = convert_to_type(custom_texts, Type.TEXT)
|
|
284
|
+
|
|
285
|
+
return custom_column
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def find_time_format_name(time_format: CustomDateFormat | None) -> str:
|
|
289
|
+
"""
|
|
290
|
+
Return the name of the format times of day are read with.
|
|
291
|
+
|
|
292
|
+
.. versionadded:: 0.1.0
|
|
293
|
+
|
|
294
|
+
Parameters
|
|
295
|
+
----------
|
|
296
|
+
time_format
|
|
297
|
+
A pattern of a time without date, or None for the default reading.
|
|
298
|
+
|
|
299
|
+
Returns
|
|
300
|
+
-------
|
|
301
|
+
str
|
|
302
|
+
The pattern, or ``HH:MM:SS`` for the default reading.
|
|
303
|
+
|
|
304
|
+
Examples
|
|
305
|
+
--------
|
|
306
|
+
>>> from numdaplot.tables.columns.time_conversion import find_time_format_name
|
|
307
|
+
>>> find_time_format_name(None)
|
|
308
|
+
'HH:MM:SS'
|
|
309
|
+
"""
|
|
310
|
+
if time_format is None:
|
|
311
|
+
return DEFAULT_TIME_FORMAT_NAME
|
|
312
|
+
|
|
313
|
+
return time_format.pattern
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Change of the time zone of a datetime column of a Table.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import numpy
|
|
8
|
+
|
|
9
|
+
from numdaplot.data_types.type import Type
|
|
10
|
+
from numdaplot.dates.time_zone_change import TimeZoneChange
|
|
11
|
+
from numdaplot.dates.time_zone_mode import TimeZoneMode
|
|
12
|
+
from numdaplot.errors.time_zone_mismatch_error import TimeZoneMismatchError
|
|
13
|
+
from numdaplot.errors.value_conversion_error import ValueConversionError
|
|
14
|
+
from numdaplot.tables.frames.column import Column
|
|
15
|
+
from numdaplot.tables.frames.column_values import find_column_missing
|
|
16
|
+
from numdaplot.tables.frames.time_zones import find_column_time_zone
|
|
17
|
+
|
|
18
|
+
MODE_OPERATIONS = {
|
|
19
|
+
TimeZoneMode.ATTRIBUTE: "Attributing a time zone",
|
|
20
|
+
TimeZoneMode.SHIFT: "Shifting to another time zone",
|
|
21
|
+
TimeZoneMode.REMOVE: "Removing the time zone",
|
|
22
|
+
}
|
|
23
|
+
# pandas marks with NaT the clock times that do not exist, or exist twice, in the zone.
|
|
24
|
+
UNREADABLE_CLOCK_TIME = "NaT"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def change_time_zone(column: Column, change: TimeZoneChange) -> Column:
|
|
28
|
+
"""
|
|
29
|
+
Return a datetime column with its time zone given, changed or removed.
|
|
30
|
+
|
|
31
|
+
.. versionadded:: 0.1.0
|
|
32
|
+
|
|
33
|
+
Parameters
|
|
34
|
+
----------
|
|
35
|
+
column
|
|
36
|
+
A datetime column.
|
|
37
|
+
change
|
|
38
|
+
The mode of the change, and the new zone for ``ATTRIBUTE`` and ``SHIFT``.
|
|
39
|
+
|
|
40
|
+
Returns
|
|
41
|
+
-------
|
|
42
|
+
Column
|
|
43
|
+
The changed column, missing values staying missing.
|
|
44
|
+
|
|
45
|
+
Raises
|
|
46
|
+
------
|
|
47
|
+
TimeZoneMismatchError
|
|
48
|
+
When ``ATTRIBUTE`` is asked for datetimes with a zone, or ``SHIFT`` and ``REMOVE`` for datetimes without.
|
|
49
|
+
ValueConversionError
|
|
50
|
+
With ``ATTRIBUTE``, at the first clock time that does not exist in the zone, or exists twice.
|
|
51
|
+
|
|
52
|
+
Examples
|
|
53
|
+
--------
|
|
54
|
+
>>> import pandas
|
|
55
|
+
>>> import numdaplot as ndp
|
|
56
|
+
>>> from numdaplot.tables.columns.time_zone_conversion import change_time_zone
|
|
57
|
+
>>> times = pandas.Series(pandas.to_datetime(["2026-07-01 10:30"]))
|
|
58
|
+
>>> paris = ndp.TimeZoneChange(mode=ndp.TimeZoneMode.ATTRIBUTE, zone=ndp.TimeZone("Europe/Paris"))
|
|
59
|
+
>>> change_time_zone(times, paris).tolist()
|
|
60
|
+
[Timestamp('2026-07-01 10:30:00+0200', tz='Europe/Paris')]
|
|
61
|
+
"""
|
|
62
|
+
time_zone = find_column_time_zone(column)
|
|
63
|
+
has_zone = time_zone is not None
|
|
64
|
+
expects_zone = change.mode != TimeZoneMode.ATTRIBUTE
|
|
65
|
+
if has_zone != expects_zone:
|
|
66
|
+
operation = MODE_OPERATIONS[change.mode]
|
|
67
|
+
raise TimeZoneMismatchError(operation, expects_zone)
|
|
68
|
+
|
|
69
|
+
if change.zone is None:
|
|
70
|
+
naive_column = column.dt.tz_localize(None)
|
|
71
|
+
return naive_column
|
|
72
|
+
|
|
73
|
+
if change.mode == TimeZoneMode.SHIFT:
|
|
74
|
+
shifted_column = column.dt.tz_convert(change.zone.name)
|
|
75
|
+
return shifted_column
|
|
76
|
+
|
|
77
|
+
attributed_column = attribute_time_zone(column, change.zone.name)
|
|
78
|
+
|
|
79
|
+
return attributed_column
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def attribute_time_zone(column: Column, zone_name: str) -> Column:
|
|
83
|
+
"""
|
|
84
|
+
Return datetimes without zone given a time zone, their clock time staying the same.
|
|
85
|
+
|
|
86
|
+
.. versionadded:: 0.1.0
|
|
87
|
+
|
|
88
|
+
Parameters
|
|
89
|
+
----------
|
|
90
|
+
column
|
|
91
|
+
A datetime column without time zone.
|
|
92
|
+
zone_name
|
|
93
|
+
The IANA name of the zone.
|
|
94
|
+
|
|
95
|
+
Returns
|
|
96
|
+
-------
|
|
97
|
+
Column
|
|
98
|
+
The datetimes in the zone.
|
|
99
|
+
|
|
100
|
+
Raises
|
|
101
|
+
------
|
|
102
|
+
ValueConversionError
|
|
103
|
+
At the first clock time that does not exist in the zone, or exists twice, when the clocks change.
|
|
104
|
+
|
|
105
|
+
Examples
|
|
106
|
+
--------
|
|
107
|
+
>>> import pandas
|
|
108
|
+
>>> import numdaplot as ndp
|
|
109
|
+
>>> from numdaplot.tables.columns.time_zone_conversion import attribute_time_zone
|
|
110
|
+
>>> try:
|
|
111
|
+
... attribute_time_zone(pandas.Series(pandas.to_datetime(["2026-03-29 02:30"])), "Europe/Paris")
|
|
112
|
+
... except ndp.ValueConversionError as error:
|
|
113
|
+
... print(error)
|
|
114
|
+
Cannot store the DATETIME value '2026-03-29 02:30:00' as DATETIME without losing information.
|
|
115
|
+
"""
|
|
116
|
+
zone_column = column.dt.tz_localize(zone_name, ambiguous=UNREADABLE_CLOCK_TIME, nonexistent=UNREADABLE_CLOCK_TIME)
|
|
117
|
+
missing = find_column_missing(column)
|
|
118
|
+
unreadable_times = zone_column.isna()
|
|
119
|
+
unreadable = unreadable_times.to_numpy(dtype=numpy.bool_)
|
|
120
|
+
rejected = unreadable & ~missing
|
|
121
|
+
has_rejected = bool(rejected.any())
|
|
122
|
+
if has_rejected:
|
|
123
|
+
rejected_times = column[rejected]
|
|
124
|
+
first_rejected_time = rejected_times.iloc[0]
|
|
125
|
+
rejected_text = str(first_rejected_time)
|
|
126
|
+
raise ValueConversionError(Type.DATETIME.name, Type.DATETIME.name, rejected_text)
|
|
127
|
+
|
|
128
|
+
return zone_column
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""
|
|
2
|
+
What to do when a file or a column already exists.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from enum import Enum, auto
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Conflict(Enum):
|
|
11
|
+
"""
|
|
12
|
+
What to do when a file to write or a column to add already exists.
|
|
13
|
+
|
|
14
|
+
Used by the ``to_*`` methods of a Table and by ``NewColumn``.
|
|
15
|
+
|
|
16
|
+
.. versionadded:: 0.1.0
|
|
17
|
+
|
|
18
|
+
Examples
|
|
19
|
+
--------
|
|
20
|
+
>>> import numdaplot as ndp
|
|
21
|
+
>>> cities = ndp.Array.from_list(["Paris", "Lyon", "Paris"])
|
|
22
|
+
>>> prices = ndp.Array.from_list([120.0, 80.0, 150.0])
|
|
23
|
+
>>> sales = ndp.Table.from_arrays({"city": cities, "price": prices})
|
|
24
|
+
>>> taxed_prices = sales.column("price") * 1.2
|
|
25
|
+
>>> sales.add_column(ndp.NewColumn(name="price", values=taxed_prices, on_conflict=ndp.Conflict.REPLACE))
|
|
26
|
+
city price
|
|
27
|
+
TEXT FLOAT64
|
|
28
|
+
0 Paris 144.0
|
|
29
|
+
1 Lyon 96.0
|
|
30
|
+
2 Paris 180.0
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
ERROR = auto()
|
|
34
|
+
"""
|
|
35
|
+
Raise an error and change nothing. Default value.
|
|
36
|
+
|
|
37
|
+
Examples
|
|
38
|
+
--------
|
|
39
|
+
>>> import numdaplot as ndp
|
|
40
|
+
>>> cities = ndp.Array.from_list(["Paris", "Lyon", "Paris"])
|
|
41
|
+
>>> prices = ndp.Array.from_list([120.0, 80.0, 150.0])
|
|
42
|
+
>>> sales = ndp.Table.from_arrays({"city": cities, "price": prices})
|
|
43
|
+
>>> taxed_prices = sales.column("price") * 1.2
|
|
44
|
+
>>> try:
|
|
45
|
+
... sales.add_column(ndp.NewColumn(name="price", values=taxed_prices, on_conflict=ndp.Conflict.ERROR))
|
|
46
|
+
... except ndp.DuplicateColumnError as error:
|
|
47
|
+
... print(error)
|
|
48
|
+
The column name 'price' appears more than once.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
REPLACE = auto()
|
|
52
|
+
"""
|
|
53
|
+
Replace the existing file or column.
|
|
54
|
+
|
|
55
|
+
Examples
|
|
56
|
+
--------
|
|
57
|
+
>>> import numdaplot as ndp
|
|
58
|
+
>>> cities = ndp.Array.from_list(["Paris", "Lyon", "Paris"])
|
|
59
|
+
>>> prices = ndp.Array.from_list([120.0, 80.0, 150.0])
|
|
60
|
+
>>> sales = ndp.Table.from_arrays({"city": cities, "price": prices})
|
|
61
|
+
>>> taxed_prices = sales.column("price") * 1.2
|
|
62
|
+
>>> sales.add_column(ndp.NewColumn(name="price", values=taxed_prices, on_conflict=ndp.Conflict.REPLACE))
|
|
63
|
+
city price
|
|
64
|
+
TEXT FLOAT64
|
|
65
|
+
0 Paris 144.0
|
|
66
|
+
1 Lyon 96.0
|
|
67
|
+
2 Paris 180.0
|
|
68
|
+
"""
|