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,81 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Which row of a group of duplicated rows is kept.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from enum import Enum, auto
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Keep(Enum):
|
|
11
|
+
"""
|
|
12
|
+
Which row of a group of duplicated rows is kept, used by ``Deduplication``.
|
|
13
|
+
|
|
14
|
+
.. versionadded:: 0.1.0
|
|
15
|
+
|
|
16
|
+
Examples
|
|
17
|
+
--------
|
|
18
|
+
>>> import numdaplot as ndp
|
|
19
|
+
>>> cities = ndp.Array.from_list(["Paris", "Lyon", "Paris"])
|
|
20
|
+
>>> prices = ndp.Array.from_list([120.0, 80.0, 150.0])
|
|
21
|
+
>>> sales = ndp.Table.from_arrays({"city": cities, "price": prices})
|
|
22
|
+
>>> sales.drop_duplicates(ndp.Deduplication(columns=["city"], keep=ndp.Keep.LAST))
|
|
23
|
+
city price
|
|
24
|
+
TEXT FLOAT64
|
|
25
|
+
0 Lyon 80.0
|
|
26
|
+
1 Paris 150.0
|
|
27
|
+
>>> sales.drop_duplicates(ndp.Deduplication(columns=["city"], keep=ndp.Keep.NONE))
|
|
28
|
+
city price
|
|
29
|
+
TEXT FLOAT64
|
|
30
|
+
0 Lyon 80.0
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
FIRST = auto()
|
|
34
|
+
"""
|
|
35
|
+
The first row of each group is kept. 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
|
+
>>> sales.drop_duplicates(ndp.Deduplication(columns=["city"], keep=ndp.Keep.FIRST))
|
|
44
|
+
city price
|
|
45
|
+
TEXT FLOAT64
|
|
46
|
+
0 Paris 120.0
|
|
47
|
+
1 Lyon 80.0
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
LAST = auto()
|
|
51
|
+
"""
|
|
52
|
+
The last row of each group is kept.
|
|
53
|
+
|
|
54
|
+
Examples
|
|
55
|
+
--------
|
|
56
|
+
>>> import numdaplot as ndp
|
|
57
|
+
>>> cities = ndp.Array.from_list(["Paris", "Lyon", "Paris"])
|
|
58
|
+
>>> prices = ndp.Array.from_list([120.0, 80.0, 150.0])
|
|
59
|
+
>>> sales = ndp.Table.from_arrays({"city": cities, "price": prices})
|
|
60
|
+
>>> sales.drop_duplicates(ndp.Deduplication(columns=["city"], keep=ndp.Keep.LAST))
|
|
61
|
+
city price
|
|
62
|
+
TEXT FLOAT64
|
|
63
|
+
0 Lyon 80.0
|
|
64
|
+
1 Paris 150.0
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
NONE = auto()
|
|
68
|
+
"""
|
|
69
|
+
No row of a duplicated group is kept, only rows that appear once remain.
|
|
70
|
+
|
|
71
|
+
Examples
|
|
72
|
+
--------
|
|
73
|
+
>>> import numdaplot as ndp
|
|
74
|
+
>>> cities = ndp.Array.from_list(["Paris", "Lyon", "Paris"])
|
|
75
|
+
>>> prices = ndp.Array.from_list([120.0, 80.0, 150.0])
|
|
76
|
+
>>> sales = ndp.Table.from_arrays({"city": cities, "price": prices})
|
|
77
|
+
>>> sales.drop_duplicates(ndp.Deduplication(columns=["city"], keep=ndp.Keep.NONE))
|
|
78
|
+
city price
|
|
79
|
+
TEXT FLOAT64
|
|
80
|
+
0 Lyon 80.0
|
|
81
|
+
"""
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
r"""
|
|
2
|
+
Whether a Table cleans the column names it reads.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from enum import Enum, auto
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ColumnNames(Enum):
|
|
11
|
+
r"""
|
|
12
|
+
Whether the column names read from a file or a pandas DataFrame are cleaned.
|
|
13
|
+
|
|
14
|
+
Cleaning removes what ``str.strip`` removes at the start and the end of each name: spaces, tabs, line breaks and
|
|
15
|
+
non-breaking spaces. The inside of a name is never changed.
|
|
16
|
+
|
|
17
|
+
.. versionadded:: 0.1.0
|
|
18
|
+
|
|
19
|
+
Examples
|
|
20
|
+
--------
|
|
21
|
+
>>> import tempfile
|
|
22
|
+
>>> from pathlib import Path
|
|
23
|
+
>>> import numdaplot as ndp
|
|
24
|
+
>>> path = Path(tempfile.mkdtemp()) / "vehicles.csv"
|
|
25
|
+
>>> _ = path.write_text('"id_vehicule\n";speed\n1;50\n')
|
|
26
|
+
>>> ndp.Table.from_csv(path, ndp.CsvReadOptions(separator=";")).column_names
|
|
27
|
+
['id_vehicule', 'speed']
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
CLEANED = auto()
|
|
31
|
+
r"""
|
|
32
|
+
The spaces, tabs and line breaks at the start and the end of each name are removed. Default value.
|
|
33
|
+
|
|
34
|
+
Examples
|
|
35
|
+
--------
|
|
36
|
+
>>> import tempfile
|
|
37
|
+
>>> from pathlib import Path
|
|
38
|
+
>>> import numdaplot as ndp
|
|
39
|
+
>>> path = Path(tempfile.mkdtemp()) / "vehicles.csv"
|
|
40
|
+
>>> _ = path.write_text('" id_vehicule\n";speed\n1;50\n')
|
|
41
|
+
>>> options = ndp.CsvReadOptions(separator=";", column_names=ndp.ColumnNames.CLEANED)
|
|
42
|
+
>>> ndp.Table.from_csv(path, options).column_names
|
|
43
|
+
['id_vehicule', 'speed']
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
KEPT = auto()
|
|
47
|
+
r"""
|
|
48
|
+
Each name is kept as written.
|
|
49
|
+
|
|
50
|
+
Examples
|
|
51
|
+
--------
|
|
52
|
+
>>> import tempfile
|
|
53
|
+
>>> from pathlib import Path
|
|
54
|
+
>>> import numdaplot as ndp
|
|
55
|
+
>>> path = Path(tempfile.mkdtemp()) / "vehicles.csv"
|
|
56
|
+
>>> _ = path.write_text('" id_vehicule\n";speed\n1;50\n')
|
|
57
|
+
>>> options = ndp.CsvReadOptions(separator=";", column_names=ndp.ColumnNames.KEPT)
|
|
58
|
+
>>> ndp.Table.from_csv(path, options).column_names
|
|
59
|
+
[' id_vehicule\n', 'speed']
|
|
60
|
+
"""
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Reading and writing CSV files.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import csv
|
|
8
|
+
import warnings
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Any, cast
|
|
11
|
+
|
|
12
|
+
import pandas
|
|
13
|
+
from pandas.api.types import infer_dtype
|
|
14
|
+
|
|
15
|
+
from numdaplot.tables.columns.column_names import require_column_names
|
|
16
|
+
from numdaplot.tables.files.csv_read_options import CsvReadOptions
|
|
17
|
+
from numdaplot.tables.files.csv_write_options import CsvWriteOptions
|
|
18
|
+
from numdaplot.tables.files.missing_texts import find_missing_settings
|
|
19
|
+
from numdaplot.tables.files.pandas_backend import NULLABLE_DTYPE_BACKEND
|
|
20
|
+
from numdaplot.tables.frames.frame_normalization import PYTHON_OBJECT_DTYPE
|
|
21
|
+
from numdaplot.tables.frames.pandas_decimals import find_exact_csv_settings
|
|
22
|
+
|
|
23
|
+
CSV_NEWLINE = ""
|
|
24
|
+
DECIMAL_FORMAT = "%.{decimals}f"
|
|
25
|
+
IGNORE_ACTION = "ignore"
|
|
26
|
+
# The kinds pandas infers for a column whose blocks were read as numbers or booleans in one place and texts in another.
|
|
27
|
+
MIXED_BLOCK_KINDS = frozenset({"mixed", "mixed-integer"})
|
|
28
|
+
TEXT_COLUMNS_SETTING = "usecols"
|
|
29
|
+
TEXT_DTYPE_SETTING = "dtype"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def read_csv_file(path: Path, options: CsvReadOptions) -> pandas.DataFrame:
|
|
33
|
+
r"""
|
|
34
|
+
Return the columns of a CSV file whose first row holds the column names, with the exact value of each decimal.
|
|
35
|
+
|
|
36
|
+
pandas reads a long file in blocks, each block guessing its own types. A column whose blocks get different types,
|
|
37
|
+
such as numbers then texts, is read again as texts, so every value keeps the text of the file, such as ``01``.
|
|
38
|
+
|
|
39
|
+
.. versionadded:: 0.1.0
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
path
|
|
44
|
+
The path of an existing CSV file.
|
|
45
|
+
options
|
|
46
|
+
The separator and the encoding of the file.
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
pandas.DataFrame
|
|
51
|
+
The columns as pandas reads them, empty for an empty file.
|
|
52
|
+
|
|
53
|
+
Raises
|
|
54
|
+
------
|
|
55
|
+
InvalidColumnNameError
|
|
56
|
+
When a column name is empty.
|
|
57
|
+
DuplicateColumnError
|
|
58
|
+
When a column name appears twice.
|
|
59
|
+
|
|
60
|
+
Examples
|
|
61
|
+
--------
|
|
62
|
+
>>> import tempfile
|
|
63
|
+
>>> from pathlib import Path
|
|
64
|
+
>>> import numdaplot as ndp
|
|
65
|
+
>>> from numdaplot.tables.files.csv_file import read_csv_file
|
|
66
|
+
>>> folder = Path(tempfile.mkdtemp())
|
|
67
|
+
>>> path = folder / "sales.csv"
|
|
68
|
+
>>> _ = path.write_text("city;price\nParis;1.5\n")
|
|
69
|
+
>>> read_csv_file(path, ndp.CsvReadOptions(separator=";"))
|
|
70
|
+
city price
|
|
71
|
+
0 Paris 1.5
|
|
72
|
+
"""
|
|
73
|
+
header = read_csv_header(path, options)
|
|
74
|
+
if header is None:
|
|
75
|
+
empty_frame = pandas.DataFrame()
|
|
76
|
+
return empty_frame
|
|
77
|
+
|
|
78
|
+
require_column_names(header)
|
|
79
|
+
block_frame = read_pandas_csv(path, options, {})
|
|
80
|
+
mixed_names = find_mixed_columns(block_frame)
|
|
81
|
+
if mixed_names == []:
|
|
82
|
+
return block_frame
|
|
83
|
+
|
|
84
|
+
text_settings = {TEXT_COLUMNS_SETTING: mixed_names, TEXT_DTYPE_SETTING: str}
|
|
85
|
+
text_frame = read_pandas_csv(path, options, text_settings)
|
|
86
|
+
text_columns = {name: text_frame[name] for name in mixed_names}
|
|
87
|
+
frame = block_frame.assign(**text_columns)
|
|
88
|
+
|
|
89
|
+
return frame
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def read_pandas_csv(path: Path, options: CsvReadOptions, column_settings: dict[str, Any]) -> pandas.DataFrame:
|
|
93
|
+
r"""
|
|
94
|
+
Return the columns of a CSV file as ``pandas.read_csv`` reads them in blocks, with the exact value of each decimal.
|
|
95
|
+
|
|
96
|
+
The ``DtypeWarning`` pandas emits when the blocks of a column get different types is not shown, as
|
|
97
|
+
``read_csv_file`` reads such a column again as texts.
|
|
98
|
+
|
|
99
|
+
.. versionadded:: 0.1.0
|
|
100
|
+
|
|
101
|
+
Parameters
|
|
102
|
+
----------
|
|
103
|
+
path
|
|
104
|
+
The path of an existing CSV file whose first row holds the column names.
|
|
105
|
+
options
|
|
106
|
+
The separator, the encoding and the texts read as missing.
|
|
107
|
+
column_settings
|
|
108
|
+
Other settings of ``pandas.read_csv``, such as the columns to read and their dtype.
|
|
109
|
+
|
|
110
|
+
Returns
|
|
111
|
+
-------
|
|
112
|
+
pandas.DataFrame
|
|
113
|
+
The columns as pandas reads them.
|
|
114
|
+
|
|
115
|
+
Examples
|
|
116
|
+
--------
|
|
117
|
+
>>> import tempfile
|
|
118
|
+
>>> from pathlib import Path
|
|
119
|
+
>>> import numdaplot as ndp
|
|
120
|
+
>>> from numdaplot.tables.files.csv_file import read_pandas_csv
|
|
121
|
+
>>> path = Path(tempfile.mkdtemp()) / "codes.csv"
|
|
122
|
+
>>> _ = path.write_text("code;price\n01;1.5\n")
|
|
123
|
+
>>> read_pandas_csv(path, ndp.CsvReadOptions(separator=";"), {"usecols": ["code"], "dtype": str})
|
|
124
|
+
code
|
|
125
|
+
0 01
|
|
126
|
+
"""
|
|
127
|
+
# Some versions of the pandas stubs leave the parameter types of read_csv unknown.
|
|
128
|
+
csv_pandas = cast(Any, pandas)
|
|
129
|
+
exact_settings = find_exact_csv_settings()
|
|
130
|
+
missing_settings = find_missing_settings(options.missing_texts)
|
|
131
|
+
with warnings.catch_warnings():
|
|
132
|
+
warnings.simplefilter(IGNORE_ACTION, pandas.errors.DtypeWarning)
|
|
133
|
+
raw_frame = csv_pandas.read_csv(
|
|
134
|
+
path,
|
|
135
|
+
sep=options.separator,
|
|
136
|
+
encoding=options.encoding.value,
|
|
137
|
+
dtype_backend=NULLABLE_DTYPE_BACKEND,
|
|
138
|
+
**exact_settings,
|
|
139
|
+
**missing_settings,
|
|
140
|
+
**column_settings,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
frame = cast(pandas.DataFrame, raw_frame)
|
|
144
|
+
|
|
145
|
+
return frame
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def find_mixed_columns(frame: pandas.DataFrame) -> list[str]:
|
|
149
|
+
"""
|
|
150
|
+
Return the names of the columns whose blocks pandas read with different types, such as numbers then texts.
|
|
151
|
+
|
|
152
|
+
A block holding only ``01`` is read as the number 1, so the text of such a column is no longer the one of the file.
|
|
153
|
+
|
|
154
|
+
.. versionadded:: 0.1.0
|
|
155
|
+
|
|
156
|
+
Parameters
|
|
157
|
+
----------
|
|
158
|
+
frame
|
|
159
|
+
The columns of a CSV file as ``pandas.read_csv`` reads them in blocks.
|
|
160
|
+
|
|
161
|
+
Returns
|
|
162
|
+
-------
|
|
163
|
+
list[str]
|
|
164
|
+
The names of the mixed columns, in the order of the file.
|
|
165
|
+
|
|
166
|
+
Examples
|
|
167
|
+
--------
|
|
168
|
+
>>> import pandas
|
|
169
|
+
>>> from numdaplot.tables.files.csv_file import find_mixed_columns
|
|
170
|
+
>>> codes = pandas.Series([1, "2A"], dtype=object)
|
|
171
|
+
>>> prices = pandas.Series([1.5, 2.0])
|
|
172
|
+
>>> find_mixed_columns(pandas.DataFrame({"code": codes, "price": prices}))
|
|
173
|
+
['code']
|
|
174
|
+
"""
|
|
175
|
+
mixed_names = list[str]()
|
|
176
|
+
for column_name, column in frame.items():
|
|
177
|
+
if column.dtype != PYTHON_OBJECT_DTYPE:
|
|
178
|
+
continue
|
|
179
|
+
|
|
180
|
+
inferred_kind = infer_dtype(column, skipna=True)
|
|
181
|
+
if inferred_kind in MIXED_BLOCK_KINDS:
|
|
182
|
+
mixed_names.append(str(column_name))
|
|
183
|
+
|
|
184
|
+
return mixed_names
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def read_csv_header(path: Path, options: CsvReadOptions) -> list[str] | None:
|
|
188
|
+
r"""
|
|
189
|
+
Return the column names written on the first row of a CSV file, before pandas renames repeated ones.
|
|
190
|
+
|
|
191
|
+
.. versionadded:: 0.1.0
|
|
192
|
+
|
|
193
|
+
Parameters
|
|
194
|
+
----------
|
|
195
|
+
path
|
|
196
|
+
The path of an existing CSV file.
|
|
197
|
+
options
|
|
198
|
+
The separator and the encoding of the file.
|
|
199
|
+
|
|
200
|
+
Returns
|
|
201
|
+
-------
|
|
202
|
+
list[str] or None
|
|
203
|
+
The names of the first row, ``None`` for an empty file.
|
|
204
|
+
|
|
205
|
+
Examples
|
|
206
|
+
--------
|
|
207
|
+
>>> import tempfile
|
|
208
|
+
>>> from pathlib import Path
|
|
209
|
+
>>> import numdaplot as ndp
|
|
210
|
+
>>> from numdaplot.tables.files.csv_file import read_csv_header
|
|
211
|
+
>>> folder = Path(tempfile.mkdtemp())
|
|
212
|
+
>>> path = folder / "sales.csv"
|
|
213
|
+
>>> _ = path.write_text("price,price\n1,2\n")
|
|
214
|
+
>>> read_csv_header(path, ndp.CsvReadOptions())
|
|
215
|
+
['price', 'price']
|
|
216
|
+
"""
|
|
217
|
+
with path.open(encoding=options.encoding.value, newline=CSV_NEWLINE) as file:
|
|
218
|
+
rows = csv.reader(file, delimiter=options.separator)
|
|
219
|
+
header = next(rows, None)
|
|
220
|
+
|
|
221
|
+
return header
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def write_csv_file(frame: pandas.DataFrame, path: Path, options: CsvWriteOptions) -> None:
|
|
225
|
+
"""
|
|
226
|
+
Write the columns of a Table in a CSV file, column names on the first row and without row numbers.
|
|
227
|
+
|
|
228
|
+
Missing values are written as empty values.
|
|
229
|
+
|
|
230
|
+
.. versionadded:: 0.1.0
|
|
231
|
+
|
|
232
|
+
Parameters
|
|
233
|
+
----------
|
|
234
|
+
frame
|
|
235
|
+
The columns of a Table.
|
|
236
|
+
path
|
|
237
|
+
The path of the file, replaced when it exists.
|
|
238
|
+
options
|
|
239
|
+
The separator and the encoding of the file.
|
|
240
|
+
|
|
241
|
+
Examples
|
|
242
|
+
--------
|
|
243
|
+
>>> import tempfile
|
|
244
|
+
>>> from pathlib import Path
|
|
245
|
+
>>> import pandas
|
|
246
|
+
>>> import numdaplot as ndp
|
|
247
|
+
>>> from numdaplot.tables.files.csv_file import write_csv_file
|
|
248
|
+
>>> path = Path(tempfile.mkdtemp()) / "sales.csv"
|
|
249
|
+
>>> write_csv_file(pandas.DataFrame({"price": [1.5]}), path, ndp.CsvWriteOptions())
|
|
250
|
+
>>> print(path.read_text())
|
|
251
|
+
price
|
|
252
|
+
1.5
|
|
253
|
+
<BLANKLINE>
|
|
254
|
+
"""
|
|
255
|
+
decimal_format = None
|
|
256
|
+
if options.decimals is not None:
|
|
257
|
+
decimal_format = DECIMAL_FORMAT.format(decimals=options.decimals)
|
|
258
|
+
|
|
259
|
+
frame.to_csv(
|
|
260
|
+
path,
|
|
261
|
+
sep=options.separator,
|
|
262
|
+
encoding=options.encoding.value,
|
|
263
|
+
index=False,
|
|
264
|
+
float_format=decimal_format,
|
|
265
|
+
)
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Settings of the CSV 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.csv_separator import DEFAULT_SEPARATOR, require_separator
|
|
12
|
+
from numdaplot.tables.files.encoding import Encoding
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class CsvReadOptions:
|
|
17
|
+
r"""
|
|
18
|
+
Settings of a CSV file read by ``Table.from_csv``.
|
|
19
|
+
|
|
20
|
+
.. versionadded:: 0.1.0
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
separator
|
|
25
|
+
The character between two values of a row, ``","`` by default.
|
|
26
|
+
encoding
|
|
27
|
+
The text encoding of the file, UTF-8 by default.
|
|
28
|
+
column_names
|
|
29
|
+
Whether the column names are cleaned, ``ColumnNames.CLEANED`` by default: the spaces, tabs and line breaks at
|
|
30
|
+
the start and the end of each name are removed. ``ColumnNames.KEPT`` keeps the names as written.
|
|
31
|
+
missing_texts
|
|
32
|
+
The texts read as missing values, compared with the whole value of each cell. When omitted, the texts pandas
|
|
33
|
+
reads as missing: ``""``, ``"#N/A"``, ``"#N/A N/A"``, ``"#NA"``, ``"-1.#IND"``, ``"-1.#QNAN"``, ``"-NaN"``,
|
|
34
|
+
``"-nan"``, ``"1.#IND"``, ``"1.#QNAN"``, ``"<NA>"``, ``"N/A"``, ``"NA"``, ``"NULL"``, ``"NaN"``, ``"None"``,
|
|
35
|
+
``"n/a"``, ``"nan"`` and ``"null"``. A given list replaces them: ``[]`` reads no value as missing, not even
|
|
36
|
+
an empty one, so a column of numbers with an empty value is read as texts.
|
|
37
|
+
|
|
38
|
+
Raises
|
|
39
|
+
------
|
|
40
|
+
InvalidTypeError
|
|
41
|
+
When a setting is not of the type its annotation names.
|
|
42
|
+
InvalidSeparatorError
|
|
43
|
+
When the separator is not exactly one character.
|
|
44
|
+
|
|
45
|
+
Examples
|
|
46
|
+
--------
|
|
47
|
+
>>> import tempfile
|
|
48
|
+
>>> from pathlib import Path
|
|
49
|
+
>>> import numdaplot as ndp
|
|
50
|
+
>>> path = Path(tempfile.mkdtemp()) / "sales.csv"
|
|
51
|
+
>>> _ = path.write_text("city;price\nParis;1.5\nLyon;8.0\n")
|
|
52
|
+
>>> ndp.Table.from_csv(path, ndp.CsvReadOptions(separator=";"))
|
|
53
|
+
city price
|
|
54
|
+
TEXT FLOAT64
|
|
55
|
+
0 Paris 1.5
|
|
56
|
+
1 Lyon 8.0
|
|
57
|
+
>>> _ = path.write_text("city;code\nParis;N/A\nLyon;\n")
|
|
58
|
+
>>> ndp.Table.from_csv(path, ndp.CsvReadOptions(separator=";", missing_texts=[""]))
|
|
59
|
+
city code
|
|
60
|
+
TEXT TEXT
|
|
61
|
+
0 Paris N/A
|
|
62
|
+
1 Lyon <NA>
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
separator: str = DEFAULT_SEPARATOR
|
|
66
|
+
encoding: Encoding = Encoding.UTF_8
|
|
67
|
+
column_names: ColumnNames = ColumnNames.CLEANED
|
|
68
|
+
missing_texts: list[str] | None = None
|
|
69
|
+
|
|
70
|
+
def __post_init__(self) -> None:
|
|
71
|
+
"""
|
|
72
|
+
Check the type of every setting, and that the separator is exactly one character.
|
|
73
|
+
|
|
74
|
+
.. versionadded:: 0.1.0
|
|
75
|
+
|
|
76
|
+
Raises
|
|
77
|
+
------
|
|
78
|
+
InvalidTypeError
|
|
79
|
+
When a setting is not of the type its annotation names.
|
|
80
|
+
InvalidSeparatorError
|
|
81
|
+
When the separator is not exactly one character.
|
|
82
|
+
"""
|
|
83
|
+
require_field_types(self)
|
|
84
|
+
|
|
85
|
+
require_separator(self.separator)
|
|
86
|
+
|
|
87
|
+
if self.missing_texts is not None:
|
|
88
|
+
missing_texts_copy = list(self.missing_texts)
|
|
89
|
+
object.__setattr__(self, "missing_texts", missing_texts_copy)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Check of the separator of a CSV file.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from numdaplot.errors.invalid_separator_error import InvalidSeparatorError
|
|
8
|
+
|
|
9
|
+
DEFAULT_SEPARATOR = ","
|
|
10
|
+
SEPARATOR_LENGTH = 1
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def require_separator(separator: str) -> None:
|
|
14
|
+
"""
|
|
15
|
+
Check that the separator of a CSV file is exactly one character.
|
|
16
|
+
|
|
17
|
+
.. versionadded:: 0.1.0
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
separator
|
|
22
|
+
The character between two values of a row.
|
|
23
|
+
|
|
24
|
+
Raises
|
|
25
|
+
------
|
|
26
|
+
InvalidSeparatorError
|
|
27
|
+
When the separator is empty or longer than one character.
|
|
28
|
+
|
|
29
|
+
Examples
|
|
30
|
+
--------
|
|
31
|
+
>>> import numdaplot as ndp
|
|
32
|
+
>>> from numdaplot.tables.files.csv_separator import require_separator
|
|
33
|
+
>>> try:
|
|
34
|
+
... require_separator(";;")
|
|
35
|
+
... except ndp.InvalidSeparatorError as error:
|
|
36
|
+
... print(error)
|
|
37
|
+
Expected a separator of exactly one character, got ';;'.
|
|
38
|
+
"""
|
|
39
|
+
separator_length = len(separator)
|
|
40
|
+
if separator_length != SEPARATOR_LENGTH:
|
|
41
|
+
raise InvalidSeparatorError(separator)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Settings of the CSV 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.csv_separator import DEFAULT_SEPARATOR, require_separator
|
|
11
|
+
from numdaplot.tables.files.decimal_count import require_decimal_count
|
|
12
|
+
from numdaplot.tables.files.encoding import Encoding
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class CsvWriteOptions:
|
|
17
|
+
"""
|
|
18
|
+
Settings of a CSV file written by ``Table.to_csv``.
|
|
19
|
+
|
|
20
|
+
.. versionadded:: 0.1.0
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
separator
|
|
25
|
+
The character between two values of a row, ``","`` by default.
|
|
26
|
+
encoding
|
|
27
|
+
The text encoding of the file, UTF-8 by default.
|
|
28
|
+
decimals
|
|
29
|
+
The number of decimals written for every decimal column, 0 or more. Each value is rounded and keeps its
|
|
30
|
+
zeros, such as ``1.50``, so the file no longer holds the exact values. When omitted, a decimal is written
|
|
31
|
+
with every digit of its value.
|
|
32
|
+
|
|
33
|
+
Raises
|
|
34
|
+
------
|
|
35
|
+
InvalidTypeError
|
|
36
|
+
When a setting is not of the type its annotation names.
|
|
37
|
+
InvalidSeparatorError
|
|
38
|
+
When the separator is not exactly one character.
|
|
39
|
+
InvalidCountError
|
|
40
|
+
When ``decimals`` is negative.
|
|
41
|
+
|
|
42
|
+
Examples
|
|
43
|
+
--------
|
|
44
|
+
>>> import tempfile
|
|
45
|
+
>>> from pathlib import Path
|
|
46
|
+
>>> import numdaplot as ndp
|
|
47
|
+
>>> path = Path(tempfile.mkdtemp()) / "sales.csv"
|
|
48
|
+
>>> prices = ndp.Table.from_arrays({"price": ndp.Array.from_list([1.5, 8.0])})
|
|
49
|
+
>>> prices.to_csv(path, ndp.CsvWriteOptions(separator=";", decimals=2))
|
|
50
|
+
>>> print(path.read_text())
|
|
51
|
+
price
|
|
52
|
+
1.50
|
|
53
|
+
8.00
|
|
54
|
+
<BLANKLINE>
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
separator: str = DEFAULT_SEPARATOR
|
|
58
|
+
encoding: Encoding = Encoding.UTF_8
|
|
59
|
+
decimals: int | None = None
|
|
60
|
+
|
|
61
|
+
def __post_init__(self) -> None:
|
|
62
|
+
"""
|
|
63
|
+
Check every setting: its type, a separator of exactly one character and ``decimals`` not negative.
|
|
64
|
+
|
|
65
|
+
.. versionadded:: 0.1.0
|
|
66
|
+
|
|
67
|
+
Raises
|
|
68
|
+
------
|
|
69
|
+
InvalidTypeError
|
|
70
|
+
When a setting is not of the type its annotation names.
|
|
71
|
+
InvalidSeparatorError
|
|
72
|
+
When the separator is not exactly one character.
|
|
73
|
+
InvalidCountError
|
|
74
|
+
When ``decimals`` is negative.
|
|
75
|
+
"""
|
|
76
|
+
require_field_types(self)
|
|
77
|
+
|
|
78
|
+
require_separator(self.separator)
|
|
79
|
+
require_decimal_count(self.decimals)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Check of the number of decimals written in a file.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from numdaplot.errors.invalid_count_error import InvalidCountError
|
|
8
|
+
|
|
9
|
+
MINIMUM_DECIMAL_COUNT = 0
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def require_decimal_count(decimals: int | None) -> None:
|
|
13
|
+
"""
|
|
14
|
+
Check that a number of written decimals, when given, is 0 or more.
|
|
15
|
+
|
|
16
|
+
.. versionadded:: 0.1.0
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
decimals
|
|
21
|
+
The number of decimals, or None when every digit is written.
|
|
22
|
+
|
|
23
|
+
Raises
|
|
24
|
+
------
|
|
25
|
+
InvalidCountError
|
|
26
|
+
When the number is negative.
|
|
27
|
+
|
|
28
|
+
Examples
|
|
29
|
+
--------
|
|
30
|
+
>>> import numdaplot as ndp
|
|
31
|
+
>>> from numdaplot.tables.files.decimal_count import require_decimal_count
|
|
32
|
+
>>> try:
|
|
33
|
+
... require_decimal_count(-1)
|
|
34
|
+
... except ndp.InvalidCountError as error:
|
|
35
|
+
... print(error)
|
|
36
|
+
Expected a count of at least 0, got -1.
|
|
37
|
+
"""
|
|
38
|
+
if decimals is None:
|
|
39
|
+
return
|
|
40
|
+
|
|
41
|
+
if decimals < MINIMUM_DECIMAL_COUNT:
|
|
42
|
+
raise InvalidCountError(decimals, MINIMUM_DECIMAL_COUNT)
|