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,203 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Reading and writing JSON files.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any, cast
|
|
10
|
+
|
|
11
|
+
import pandas
|
|
12
|
+
|
|
13
|
+
from numdaplot.tables.files.json_decimals import has_decimal_column, write_exact_objects
|
|
14
|
+
from numdaplot.tables.files.json_layout import JsonLayout
|
|
15
|
+
from numdaplot.tables.files.json_read_options import JsonReadOptions
|
|
16
|
+
from numdaplot.tables.files.json_write_options import JsonWriteOptions
|
|
17
|
+
|
|
18
|
+
JSON_ENCODING = "utf-8"
|
|
19
|
+
RECORDS_ORIENTATION = "records"
|
|
20
|
+
ISO_DATE_FORMAT = "iso"
|
|
21
|
+
PYTHON_OBJECT_DTYPE = object
|
|
22
|
+
WRITE_MODE = "w"
|
|
23
|
+
LINE_END = "\n"
|
|
24
|
+
OBJECT_SEPARATOR = ","
|
|
25
|
+
LIST_FORMAT = "[{objects}]"
|
|
26
|
+
UNCHANGED_NEWLINES = ""
|
|
27
|
+
EMPTY_LINES_TEXT = ""
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def read_json_file(path: Path, options: JsonReadOptions) -> pandas.DataFrame:
|
|
31
|
+
"""
|
|
32
|
+
Return the columns of a JSON file holding one object per row.
|
|
33
|
+
|
|
34
|
+
The values are kept as Python objects, so a Table guesses each type from the values of the file
|
|
35
|
+
only: a text that looks like a number or a date stays a text.
|
|
36
|
+
|
|
37
|
+
.. versionadded:: 0.1.0
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
path
|
|
42
|
+
The path of an existing JSON file, in UTF-8.
|
|
43
|
+
options
|
|
44
|
+
The layout of the rows.
|
|
45
|
+
|
|
46
|
+
Returns
|
|
47
|
+
-------
|
|
48
|
+
pandas.DataFrame
|
|
49
|
+
One column per name found in the objects, holding Python objects.
|
|
50
|
+
|
|
51
|
+
Examples
|
|
52
|
+
--------
|
|
53
|
+
>>> import tempfile
|
|
54
|
+
>>> from pathlib import Path
|
|
55
|
+
>>> import numdaplot as ndp
|
|
56
|
+
>>> from numdaplot.tables.files.json_file import read_json_file
|
|
57
|
+
>>> path = Path(tempfile.mkdtemp()) / "sales.json"
|
|
58
|
+
>>> _ = path.write_text('[{"city": "Paris", "count": 2}]')
|
|
59
|
+
>>> read_json_file(path, ndp.JsonReadOptions())
|
|
60
|
+
city count
|
|
61
|
+
0 Paris 2
|
|
62
|
+
"""
|
|
63
|
+
with path.open(encoding=JSON_ENCODING) as file:
|
|
64
|
+
if options.layout == JsonLayout.LINES:
|
|
65
|
+
content = file.read()
|
|
66
|
+
records = read_json_lines(content)
|
|
67
|
+
else:
|
|
68
|
+
records = json.load(file)
|
|
69
|
+
|
|
70
|
+
frame = pandas.DataFrame(records, dtype=PYTHON_OBJECT_DTYPE)
|
|
71
|
+
|
|
72
|
+
return frame
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def read_json_lines(content: str) -> list[Any]:
|
|
76
|
+
r"""
|
|
77
|
+
Return the objects of a JSON Lines text, one per line, skipping blank lines.
|
|
78
|
+
|
|
79
|
+
.. versionadded:: 0.1.0
|
|
80
|
+
|
|
81
|
+
Parameters
|
|
82
|
+
----------
|
|
83
|
+
content
|
|
84
|
+
The whole text of the file.
|
|
85
|
+
|
|
86
|
+
Returns
|
|
87
|
+
-------
|
|
88
|
+
list[Any]
|
|
89
|
+
One decoded object per line that is not blank.
|
|
90
|
+
|
|
91
|
+
Examples
|
|
92
|
+
--------
|
|
93
|
+
>>> from numdaplot.tables.files.json_file import read_json_lines
|
|
94
|
+
>>> read_json_lines('{"price": 1}\n\n{"price": 2}\n')
|
|
95
|
+
[{'price': 1}, {'price': 2}]
|
|
96
|
+
"""
|
|
97
|
+
lines = content.splitlines()
|
|
98
|
+
records = list[Any]()
|
|
99
|
+
|
|
100
|
+
for line in lines:
|
|
101
|
+
stripped_line = line.strip()
|
|
102
|
+
if stripped_line == "":
|
|
103
|
+
continue
|
|
104
|
+
|
|
105
|
+
record = json.loads(stripped_line)
|
|
106
|
+
records.append(record)
|
|
107
|
+
|
|
108
|
+
return records
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def write_json_file(frame: pandas.DataFrame, path: Path, options: JsonWriteOptions) -> None:
|
|
112
|
+
"""
|
|
113
|
+
Write the columns of a Table in a JSON file, one object per row, in UTF-8.
|
|
114
|
+
|
|
115
|
+
Missing values are written as ``null``, dates and durations in the ISO 8601 format, and decimals with every
|
|
116
|
+
digit of their value unless ``options`` gives their number.
|
|
117
|
+
|
|
118
|
+
.. versionadded:: 0.1.0
|
|
119
|
+
|
|
120
|
+
Parameters
|
|
121
|
+
----------
|
|
122
|
+
frame
|
|
123
|
+
The columns of a Table.
|
|
124
|
+
path
|
|
125
|
+
The path of the file, replaced when it exists.
|
|
126
|
+
options
|
|
127
|
+
The layout of the rows and the number of decimals.
|
|
128
|
+
|
|
129
|
+
Raises
|
|
130
|
+
------
|
|
131
|
+
ValueConversionError
|
|
132
|
+
At the first infinite value of a decimal column, which JSON cannot write.
|
|
133
|
+
|
|
134
|
+
Examples
|
|
135
|
+
--------
|
|
136
|
+
>>> import tempfile
|
|
137
|
+
>>> from pathlib import Path
|
|
138
|
+
>>> import pandas
|
|
139
|
+
>>> import numdaplot as ndp
|
|
140
|
+
>>> from numdaplot.tables.files.json_file import write_json_file
|
|
141
|
+
>>> path = Path(tempfile.mkdtemp()) / "sales.json"
|
|
142
|
+
>>> write_json_file(pandas.DataFrame({"price": [1.5]}), path, ndp.JsonWriteOptions())
|
|
143
|
+
>>> path.read_text()
|
|
144
|
+
'[{"price":1.5}]'
|
|
145
|
+
"""
|
|
146
|
+
writes_lines = options.layout == JsonLayout.LINES
|
|
147
|
+
has_decimals = has_decimal_column(frame)
|
|
148
|
+
if has_decimals:
|
|
149
|
+
objects = write_exact_objects(frame, options.decimals)
|
|
150
|
+
file_text = join_objects(objects, writes_lines)
|
|
151
|
+
with path.open(WRITE_MODE, encoding=JSON_ENCODING, newline=UNCHANGED_NEWLINES) as file:
|
|
152
|
+
file.write(file_text)
|
|
153
|
+
|
|
154
|
+
return
|
|
155
|
+
|
|
156
|
+
# Some versions of the pandas stubs leave the parameter types of to_json unknown.
|
|
157
|
+
json_frame = cast(Any, frame)
|
|
158
|
+
json_frame.to_json(
|
|
159
|
+
path,
|
|
160
|
+
orient=RECORDS_ORIENTATION,
|
|
161
|
+
lines=writes_lines,
|
|
162
|
+
force_ascii=False,
|
|
163
|
+
date_format=ISO_DATE_FORMAT,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def join_objects(objects: list[str], writes_lines: bool) -> str:
|
|
168
|
+
r"""
|
|
169
|
+
Return the whole text of a JSON file from its objects.
|
|
170
|
+
|
|
171
|
+
.. versionadded:: 0.1.0
|
|
172
|
+
|
|
173
|
+
Parameters
|
|
174
|
+
----------
|
|
175
|
+
objects
|
|
176
|
+
One JSON object per row.
|
|
177
|
+
writes_lines
|
|
178
|
+
True for one object per line, False for one list holding them.
|
|
179
|
+
|
|
180
|
+
Returns
|
|
181
|
+
-------
|
|
182
|
+
str
|
|
183
|
+
The text of the file, each line ending with a line break in the layout of one object per line.
|
|
184
|
+
|
|
185
|
+
Examples
|
|
186
|
+
--------
|
|
187
|
+
>>> from numdaplot.tables.files.json_file import join_objects
|
|
188
|
+
>>> join_objects(['{"a":1}', '{"a":2}'], False)
|
|
189
|
+
'[{"a":1},{"a":2}]'
|
|
190
|
+
>>> join_objects(['{"a":1}', '{"a":2}'], True)
|
|
191
|
+
'{"a":1}\n{"a":2}\n'
|
|
192
|
+
"""
|
|
193
|
+
if not writes_lines:
|
|
194
|
+
joined_objects = OBJECT_SEPARATOR.join(objects)
|
|
195
|
+
list_text = LIST_FORMAT.format(objects=joined_objects)
|
|
196
|
+
return list_text
|
|
197
|
+
|
|
198
|
+
if objects == []:
|
|
199
|
+
return EMPTY_LINES_TEXT
|
|
200
|
+
|
|
201
|
+
lines_text = LINE_END.join(objects) + LINE_END
|
|
202
|
+
|
|
203
|
+
return lines_text
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Layouts of the rows of a JSON file.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from enum import Enum, auto
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class JsonLayout(Enum):
|
|
11
|
+
"""
|
|
12
|
+
Layout of the rows of a JSON file, used by ``JsonReadOptions`` and ``JsonWriteOptions``.
|
|
13
|
+
|
|
14
|
+
.. versionadded:: 0.1.0
|
|
15
|
+
|
|
16
|
+
Examples
|
|
17
|
+
--------
|
|
18
|
+
>>> import tempfile
|
|
19
|
+
>>> from pathlib import Path
|
|
20
|
+
>>> import numdaplot as ndp
|
|
21
|
+
>>> folder = Path(tempfile.mkdtemp())
|
|
22
|
+
>>> path = folder / "sales.jsonl"
|
|
23
|
+
>>> prices = ndp.Table.from_arrays({"price": ndp.Array.from_list([1.5, 8.0])})
|
|
24
|
+
>>> prices.to_json(path, ndp.JsonWriteOptions(layout=ndp.JsonLayout.LINES))
|
|
25
|
+
>>> print(path.read_text())
|
|
26
|
+
{"price":1.5}
|
|
27
|
+
{"price":8.0}
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
RECORDS = auto()
|
|
31
|
+
"""
|
|
32
|
+
One list holding one object per row: ``[{"city": "Paris"}, {"city": "Lyon"}]``. Default value.
|
|
33
|
+
|
|
34
|
+
Examples
|
|
35
|
+
--------
|
|
36
|
+
>>> import tempfile
|
|
37
|
+
>>> from pathlib import Path
|
|
38
|
+
>>> import numdaplot as ndp
|
|
39
|
+
>>> folder = Path(tempfile.mkdtemp())
|
|
40
|
+
>>> path = folder / "prices.json"
|
|
41
|
+
>>> prices = ndp.Table.from_arrays({"price": ndp.Array.from_list([1.5, 8.0])})
|
|
42
|
+
>>> prices.to_json(path, ndp.JsonWriteOptions(layout=ndp.JsonLayout.RECORDS))
|
|
43
|
+
>>> print(path.read_text())
|
|
44
|
+
[{"price":1.5},{"price":8.0}]
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
LINES = auto()
|
|
48
|
+
"""
|
|
49
|
+
One object per line, without enclosing list, also called JSON Lines.
|
|
50
|
+
|
|
51
|
+
Examples
|
|
52
|
+
--------
|
|
53
|
+
>>> import tempfile
|
|
54
|
+
>>> from pathlib import Path
|
|
55
|
+
>>> import numdaplot as ndp
|
|
56
|
+
>>> folder = Path(tempfile.mkdtemp())
|
|
57
|
+
>>> path = folder / "prices.json"
|
|
58
|
+
>>> prices = ndp.Table.from_arrays({"price": ndp.Array.from_list([1.5, 8.0])})
|
|
59
|
+
>>> prices.to_json(path, ndp.JsonWriteOptions(layout=ndp.JsonLayout.LINES))
|
|
60
|
+
>>> print(path.read_text())
|
|
61
|
+
{"price":1.5}
|
|
62
|
+
{"price":8.0}
|
|
63
|
+
"""
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Settings of the JSON files a Table reads.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
|
|
9
|
+
from numdaplot.settings.field_types import require_field_types
|
|
10
|
+
from numdaplot.tables.files.column_names import ColumnNames
|
|
11
|
+
from numdaplot.tables.files.json_layout import JsonLayout
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class JsonReadOptions:
|
|
16
|
+
r"""
|
|
17
|
+
Settings of a JSON file read by ``Table.from_json``.
|
|
18
|
+
|
|
19
|
+
JSON files are always read in UTF-8.
|
|
20
|
+
|
|
21
|
+
.. versionadded:: 0.1.0
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
layout
|
|
26
|
+
The layout of the rows, one list of objects by default.
|
|
27
|
+
column_names
|
|
28
|
+
Whether the column names are cleaned, ``ColumnNames.CLEANED`` by default: the spaces, tabs and line breaks at
|
|
29
|
+
the start and the end of each name are removed. ``ColumnNames.KEPT`` keeps the names as written.
|
|
30
|
+
|
|
31
|
+
Raises
|
|
32
|
+
------
|
|
33
|
+
InvalidTypeError
|
|
34
|
+
When a setting is not of the type its annotation names.
|
|
35
|
+
|
|
36
|
+
Examples
|
|
37
|
+
--------
|
|
38
|
+
>>> import tempfile
|
|
39
|
+
>>> from pathlib import Path
|
|
40
|
+
>>> import numdaplot as ndp
|
|
41
|
+
>>> path = Path(tempfile.mkdtemp()) / "sales.jsonl"
|
|
42
|
+
>>> _ = path.write_text('{"city": "Paris", "count": 2}\n{"city": "Lyon", "count": 5}\n')
|
|
43
|
+
>>> ndp.Table.from_json(path, ndp.JsonReadOptions(layout=ndp.JsonLayout.LINES))
|
|
44
|
+
city count
|
|
45
|
+
TEXT INT64
|
|
46
|
+
0 Paris 2
|
|
47
|
+
1 Lyon 5
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
layout: JsonLayout = JsonLayout.RECORDS
|
|
51
|
+
column_names: ColumnNames = ColumnNames.CLEANED
|
|
52
|
+
|
|
53
|
+
def __post_init__(self) -> None:
|
|
54
|
+
"""
|
|
55
|
+
Check the type of every setting.
|
|
56
|
+
|
|
57
|
+
.. versionadded:: 0.1.0
|
|
58
|
+
|
|
59
|
+
Raises
|
|
60
|
+
------
|
|
61
|
+
InvalidTypeError
|
|
62
|
+
When a setting is not of the type its annotation names.
|
|
63
|
+
"""
|
|
64
|
+
require_field_types(self)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Settings of the JSON files a Table writes.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
|
|
9
|
+
from numdaplot.settings.field_types import require_field_types
|
|
10
|
+
from numdaplot.tables.files.decimal_count import require_decimal_count
|
|
11
|
+
from numdaplot.tables.files.json_layout import JsonLayout
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class JsonWriteOptions:
|
|
16
|
+
"""
|
|
17
|
+
Settings of a JSON file written by ``Table.to_json``.
|
|
18
|
+
|
|
19
|
+
JSON files are always written in UTF-8.
|
|
20
|
+
|
|
21
|
+
.. versionadded:: 0.1.0
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
layout
|
|
26
|
+
The layout of the rows, one list of objects by default.
|
|
27
|
+
decimals
|
|
28
|
+
The number of decimals written for every decimal column, 0 or more. Each value is rounded and keeps its
|
|
29
|
+
zeros, such as ``1.50``, so the file no longer holds the exact values. When omitted, a decimal is written
|
|
30
|
+
with every digit of its value.
|
|
31
|
+
|
|
32
|
+
Raises
|
|
33
|
+
------
|
|
34
|
+
InvalidTypeError
|
|
35
|
+
When a setting is not of the type its annotation names.
|
|
36
|
+
InvalidCountError
|
|
37
|
+
When ``decimals`` is negative.
|
|
38
|
+
|
|
39
|
+
Examples
|
|
40
|
+
--------
|
|
41
|
+
>>> import tempfile
|
|
42
|
+
>>> from pathlib import Path
|
|
43
|
+
>>> import numdaplot as ndp
|
|
44
|
+
>>> path = Path(tempfile.mkdtemp()) / "sales.jsonl"
|
|
45
|
+
>>> prices = ndp.Table.from_arrays({"price": ndp.Array.from_list([1.5, 8.0])})
|
|
46
|
+
>>> prices.to_json(path, ndp.JsonWriteOptions(layout=ndp.JsonLayout.LINES, decimals=2))
|
|
47
|
+
>>> print(path.read_text())
|
|
48
|
+
{"price":1.50}
|
|
49
|
+
{"price":8.00}
|
|
50
|
+
<BLANKLINE>
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
layout: JsonLayout = JsonLayout.RECORDS
|
|
54
|
+
decimals: int | None = None
|
|
55
|
+
|
|
56
|
+
def __post_init__(self) -> None:
|
|
57
|
+
"""
|
|
58
|
+
Check the type of every setting, and that ``decimals`` is not negative.
|
|
59
|
+
|
|
60
|
+
.. versionadded:: 0.1.0
|
|
61
|
+
|
|
62
|
+
Raises
|
|
63
|
+
------
|
|
64
|
+
InvalidTypeError
|
|
65
|
+
When a setting is not of the type its annotation names.
|
|
66
|
+
InvalidCountError
|
|
67
|
+
When ``decimals`` is negative.
|
|
68
|
+
"""
|
|
69
|
+
require_field_types(self)
|
|
70
|
+
|
|
71
|
+
require_decimal_count(self.decimals)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Texts read as missing values in CSV and Excel files.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
# The texts pandas reads as missing by default, written here so that the reading never depends on the pandas version.
|
|
10
|
+
DEFAULT_MISSING_TEXTS = (
|
|
11
|
+
"",
|
|
12
|
+
"#N/A",
|
|
13
|
+
"#N/A N/A",
|
|
14
|
+
"#NA",
|
|
15
|
+
"-1.#IND",
|
|
16
|
+
"-1.#QNAN",
|
|
17
|
+
"-NaN",
|
|
18
|
+
"-nan",
|
|
19
|
+
"1.#IND",
|
|
20
|
+
"1.#QNAN",
|
|
21
|
+
"<NA>",
|
|
22
|
+
"N/A",
|
|
23
|
+
"NA",
|
|
24
|
+
"NULL",
|
|
25
|
+
"NaN",
|
|
26
|
+
"None",
|
|
27
|
+
"n/a",
|
|
28
|
+
"nan",
|
|
29
|
+
"null",
|
|
30
|
+
)
|
|
31
|
+
DEFAULT_MISSING_SETTING = "keep_default_na"
|
|
32
|
+
MISSING_VALUES_SETTING = "na_values"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def find_missing_settings(missing_texts: list[str] | None) -> dict[str, Any]:
|
|
36
|
+
"""
|
|
37
|
+
Return the settings of ``pandas.read_csv`` or ``pandas.read_excel`` reading exactly the given texts as missing.
|
|
38
|
+
|
|
39
|
+
.. versionadded:: 0.1.0
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
missing_texts
|
|
44
|
+
The texts read as missing, the default texts of ``DEFAULT_MISSING_TEXTS`` when None.
|
|
45
|
+
|
|
46
|
+
Returns
|
|
47
|
+
-------
|
|
48
|
+
dict[str, Any]
|
|
49
|
+
The pandas settings, which never add the pandas default texts to the given ones.
|
|
50
|
+
|
|
51
|
+
Examples
|
|
52
|
+
--------
|
|
53
|
+
>>> from numdaplot.tables.files.missing_texts import find_missing_settings
|
|
54
|
+
>>> find_missing_settings(["N/A"])
|
|
55
|
+
{'keep_default_na': False, 'na_values': ['N/A']}
|
|
56
|
+
"""
|
|
57
|
+
read_texts = list(DEFAULT_MISSING_TEXTS)
|
|
58
|
+
if missing_texts is not None:
|
|
59
|
+
read_texts = list(missing_texts)
|
|
60
|
+
|
|
61
|
+
missing_settings = {DEFAULT_MISSING_SETTING: False, MISSING_VALUES_SETTING: read_texts}
|
|
62
|
+
|
|
63
|
+
return missing_settings
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Packages that only some file formats need.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from importlib.util import find_spec
|
|
8
|
+
|
|
9
|
+
from numdaplot.errors.missing_dependency_error import MissingDependencyError
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def require_package(package_name: str, extra_name: str) -> None:
|
|
13
|
+
"""
|
|
14
|
+
Check that an optional package is installed.
|
|
15
|
+
|
|
16
|
+
.. versionadded:: 0.1.0
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
package_name
|
|
21
|
+
The name of the package to import, such as ``openpyxl``.
|
|
22
|
+
extra_name
|
|
23
|
+
The numdaplot extra that installs it, such as ``excel``.
|
|
24
|
+
|
|
25
|
+
Raises
|
|
26
|
+
------
|
|
27
|
+
MissingDependencyError
|
|
28
|
+
When the package is not installed, with the command that installs it.
|
|
29
|
+
|
|
30
|
+
Examples
|
|
31
|
+
--------
|
|
32
|
+
>>> import numdaplot as ndp
|
|
33
|
+
>>> from numdaplot.tables.files.optional_package import require_package
|
|
34
|
+
>>> try:
|
|
35
|
+
... require_package("package_that_is_not_installed", "excel")
|
|
36
|
+
... except ndp.MissingDependencyError as error:
|
|
37
|
+
... print(error)
|
|
38
|
+
This file format needs the package_that_is_not_installed package, install it with: pip install numdaplot[excel]
|
|
39
|
+
"""
|
|
40
|
+
package_spec = find_spec(package_name)
|
|
41
|
+
if package_spec is None:
|
|
42
|
+
raise MissingDependencyError(package_name, extra_name)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""
|
|
2
|
+
How pandas stores the columns it reads from a file.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
NULLABLE_DTYPE_BACKEND = "numpy_nullable"
|
|
8
|
+
"""The pandas setting reading integers, booleans and texts in dtypes that accept missing values.
|
|
9
|
+
|
|
10
|
+
.. versionadded:: 0.1.0
|
|
11
|
+
"""
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Reading and writing Parquet files.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any, cast
|
|
9
|
+
|
|
10
|
+
import pandas
|
|
11
|
+
|
|
12
|
+
from numdaplot.tables.files.optional_package import require_package
|
|
13
|
+
from numdaplot.tables.files.pandas_backend import NULLABLE_DTYPE_BACKEND
|
|
14
|
+
|
|
15
|
+
PARQUET_PACKAGE = "pyarrow"
|
|
16
|
+
PARQUET_EXTRA = "parquet"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def read_parquet_file(path: Path) -> pandas.DataFrame:
|
|
20
|
+
"""
|
|
21
|
+
Return the columns of a Parquet file.
|
|
22
|
+
|
|
23
|
+
.. versionadded:: 0.1.0
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
path
|
|
28
|
+
The path of an existing Parquet file.
|
|
29
|
+
|
|
30
|
+
Returns
|
|
31
|
+
-------
|
|
32
|
+
pandas.DataFrame
|
|
33
|
+
The columns as pandas reads them.
|
|
34
|
+
|
|
35
|
+
Raises
|
|
36
|
+
------
|
|
37
|
+
MissingDependencyError
|
|
38
|
+
When ``pyarrow`` is not installed.
|
|
39
|
+
|
|
40
|
+
Examples
|
|
41
|
+
--------
|
|
42
|
+
>>> import tempfile
|
|
43
|
+
>>> from pathlib import Path
|
|
44
|
+
>>> import pandas
|
|
45
|
+
>>> from numdaplot.tables.files.parquet_file import read_parquet_file
|
|
46
|
+
>>> path = Path(tempfile.mkdtemp()) / "sales.parquet"
|
|
47
|
+
>>> pandas.DataFrame({"price": [1.5]}).to_parquet(path, index=False)
|
|
48
|
+
>>> read_parquet_file(path)
|
|
49
|
+
price
|
|
50
|
+
0 1.5
|
|
51
|
+
"""
|
|
52
|
+
require_package(PARQUET_PACKAGE, PARQUET_EXTRA)
|
|
53
|
+
# Some versions of the pandas stubs leave the parameter types of read_parquet unknown.
|
|
54
|
+
parquet_pandas = cast(Any, pandas)
|
|
55
|
+
raw_frame = parquet_pandas.read_parquet(path, dtype_backend=NULLABLE_DTYPE_BACKEND)
|
|
56
|
+
frame = cast(pandas.DataFrame, raw_frame)
|
|
57
|
+
|
|
58
|
+
return frame
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def write_parquet_file(frame: pandas.DataFrame, path: Path) -> None:
|
|
62
|
+
"""
|
|
63
|
+
Write the columns of a Table in a Parquet file, which keeps the type of each column.
|
|
64
|
+
|
|
65
|
+
.. versionadded:: 0.1.0
|
|
66
|
+
|
|
67
|
+
Parameters
|
|
68
|
+
----------
|
|
69
|
+
frame
|
|
70
|
+
The columns of a Table.
|
|
71
|
+
path
|
|
72
|
+
The path of the file, replaced when it exists.
|
|
73
|
+
|
|
74
|
+
Raises
|
|
75
|
+
------
|
|
76
|
+
MissingDependencyError
|
|
77
|
+
When ``pyarrow`` is not installed.
|
|
78
|
+
|
|
79
|
+
Examples
|
|
80
|
+
--------
|
|
81
|
+
>>> import tempfile
|
|
82
|
+
>>> from pathlib import Path
|
|
83
|
+
>>> import pandas
|
|
84
|
+
>>> from numdaplot.tables.files.parquet_file import write_parquet_file
|
|
85
|
+
>>> path = Path(tempfile.mkdtemp()) / "sales.parquet"
|
|
86
|
+
>>> write_parquet_file(pandas.DataFrame({"price": [1.5]}), path)
|
|
87
|
+
>>> path.exists()
|
|
88
|
+
True
|
|
89
|
+
"""
|
|
90
|
+
require_package(PARQUET_PACKAGE, PARQUET_EXTRA)
|
|
91
|
+
frame.to_parquet(path, index=False)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
r"""
|
|
2
|
+
Settings of the Parquet files a Table reads.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
|
|
9
|
+
from numdaplot.settings.field_types import require_field_types
|
|
10
|
+
from numdaplot.tables.files.column_names import ColumnNames
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
|
+
class ParquetReadOptions:
|
|
15
|
+
r"""
|
|
16
|
+
Settings of a Parquet file (``.parquet``) read by ``Table.from_parquet``.
|
|
17
|
+
|
|
18
|
+
.. versionadded:: 0.1.0
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
column_names
|
|
23
|
+
Whether the column names are cleaned, ``ColumnNames.CLEANED`` by default: the spaces, tabs and line breaks at
|
|
24
|
+
the start and the end of each name are removed. ``ColumnNames.KEPT`` keeps the names as written.
|
|
25
|
+
|
|
26
|
+
Raises
|
|
27
|
+
------
|
|
28
|
+
InvalidTypeError
|
|
29
|
+
When a setting is not of the type its annotation names.
|
|
30
|
+
|
|
31
|
+
Examples
|
|
32
|
+
--------
|
|
33
|
+
>>> import tempfile
|
|
34
|
+
>>> from pathlib import Path
|
|
35
|
+
>>> import numdaplot as ndp
|
|
36
|
+
>>> path = Path(tempfile.mkdtemp()) / "sales.parquet"
|
|
37
|
+
>>> ndp.Table.from_arrays({" price": ndp.Array.from_list([1.5])}).to_parquet(path)
|
|
38
|
+
>>> options = ndp.ParquetReadOptions(column_names=ndp.ColumnNames.KEPT)
|
|
39
|
+
>>> ndp.Table.from_parquet(path, options).column_names
|
|
40
|
+
[' price']
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
column_names: ColumnNames = ColumnNames.CLEANED
|
|
44
|
+
|
|
45
|
+
def __post_init__(self) -> None:
|
|
46
|
+
"""
|
|
47
|
+
Check the type of every setting.
|
|
48
|
+
|
|
49
|
+
.. versionadded:: 0.1.0
|
|
50
|
+
|
|
51
|
+
Raises
|
|
52
|
+
------
|
|
53
|
+
InvalidTypeError
|
|
54
|
+
When a setting is not of the type its annotation names.
|
|
55
|
+
"""
|
|
56
|
+
require_field_types(self)
|