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.
Files changed (474) hide show
  1. numdaplot/__init__.py +506 -0
  2. numdaplot/arrays/__init__.py +5 -0
  3. numdaplot/arrays/array.py +92 -0
  4. numdaplot/arrays/array_arithmetic.py +404 -0
  5. numdaplot/arrays/array_calculation.py +143 -0
  6. numdaplot/arrays/array_conversion.py +150 -0
  7. numdaplot/arrays/array_creation.py +371 -0
  8. numdaplot/arrays/array_data.py +281 -0
  9. numdaplot/arrays/array_layout.py +179 -0
  10. numdaplot/arrays/array_logic.py +227 -0
  11. numdaplot/arrays/array_reflected_arithmetic.py +334 -0
  12. numdaplot/arrays/array_refusals.py +339 -0
  13. numdaplot/arrays/array_selection.py +195 -0
  14. numdaplot/arrays/array_sorting.py +59 -0
  15. numdaplot/arrays/axis_number.py +58 -0
  16. numdaplot/arrays/calculation/__init__.py +5 -0
  17. numdaplot/arrays/calculation/counting_statistics.py +325 -0
  18. numdaplot/arrays/calculation/location_statistics.py +268 -0
  19. numdaplot/arrays/calculation/math_function_values.py +183 -0
  20. numdaplot/arrays/calculation/statistic_values.py +209 -0
  21. numdaplot/arrays/calculation/time_function_values.py +419 -0
  22. numdaplot/arrays/conversion/__init__.py +5 -0
  23. numdaplot/arrays/conversion/array_text.py +62 -0
  24. numdaplot/arrays/conversion/equality_check.py +72 -0
  25. numdaplot/arrays/conversion/python_values.py +70 -0
  26. numdaplot/arrays/conversion/time_text.py +290 -0
  27. numdaplot/arrays/creation/__init__.py +5 -0
  28. numdaplot/arrays/creation/date_parts.py +89 -0
  29. numdaplot/arrays/creation/date_parts_values.py +437 -0
  30. numdaplot/arrays/creation/distribution.py +54 -0
  31. numdaplot/arrays/creation/filled_values.py +58 -0
  32. numdaplot/arrays/creation/list_conversion.py +311 -0
  33. numdaplot/arrays/creation/list_shape.py +97 -0
  34. numdaplot/arrays/creation/normal.py +65 -0
  35. numdaplot/arrays/creation/numpy_conversion.py +149 -0
  36. numdaplot/arrays/creation/random_integers.py +104 -0
  37. numdaplot/arrays/creation/random_values.py +97 -0
  38. numdaplot/arrays/creation/range_values.py +73 -0
  39. numdaplot/arrays/creation/spacing.py +84 -0
  40. numdaplot/arrays/creation/spacing_values.py +63 -0
  41. numdaplot/arrays/creation/uniform.py +63 -0
  42. numdaplot/arrays/equality.py +68 -0
  43. numdaplot/arrays/layout/__init__.py +5 -0
  44. numdaplot/arrays/layout/sorting_values.py +113 -0
  45. numdaplot/arrays/layout/unique_values.py +49 -0
  46. numdaplot/arrays/mapping/__init__.py +5 -0
  47. numdaplot/arrays/mapping/mapped_values.py +286 -0
  48. numdaplot/arrays/mapping/unmatched.py +50 -0
  49. numdaplot/arrays/mapping/value_change.py +55 -0
  50. numdaplot/arrays/mapping/value_mapping.py +161 -0
  51. numdaplot/arrays/math_functions/__init__.py +5 -0
  52. numdaplot/arrays/math_functions/absolute.py +27 -0
  53. numdaplot/arrays/math_functions/cosine.py +28 -0
  54. numdaplot/arrays/math_functions/exponential.py +27 -0
  55. numdaplot/arrays/math_functions/logarithm.py +72 -0
  56. numdaplot/arrays/math_functions/math_function.py +58 -0
  57. numdaplot/arrays/math_functions/round.py +58 -0
  58. numdaplot/arrays/math_functions/sine.py +28 -0
  59. numdaplot/arrays/math_functions/square_root.py +27 -0
  60. numdaplot/arrays/operations/__init__.py +5 -0
  61. numdaplot/arrays/operations/boolean_operands.py +48 -0
  62. numdaplot/arrays/operations/combination.py +157 -0
  63. numdaplot/arrays/operations/float_errors.py +170 -0
  64. numdaplot/arrays/operations/integer_bounds.py +175 -0
  65. numdaplot/arrays/operations/integer_rules.py +397 -0
  66. numdaplot/arrays/operations/operand.py +139 -0
  67. numdaplot/arrays/operations/time_arithmetic.py +479 -0
  68. numdaplot/arrays/operations/time_bounds.py +286 -0
  69. numdaplot/arrays/operations/time_result_bounds.py +397 -0
  70. numdaplot/arrays/operations/transformation.py +54 -0
  71. numdaplot/arrays/operations/type_requirements.py +94 -0
  72. numdaplot/arrays/replacement.py +66 -0
  73. numdaplot/arrays/selection/__init__.py +5 -0
  74. numdaplot/arrays/selection/comparison_masks.py +131 -0
  75. numdaplot/arrays/selection/membership_masks.py +118 -0
  76. numdaplot/arrays/selection/missing_mask.py +50 -0
  77. numdaplot/arrays/selection/region_index.py +178 -0
  78. numdaplot/arrays/selection/replaced_values.py +120 -0
  79. numdaplot/arrays/selection/rule_mask.py +83 -0
  80. numdaplot/arrays/selection/time_reference.py +172 -0
  81. numdaplot/arrays/shape.py +74 -0
  82. numdaplot/arrays/type_match.py +51 -0
  83. numdaplot/data_types/__init__.py +5 -0
  84. numdaplot/data_types/library.py +57 -0
  85. numdaplot/data_types/numpy_mapping.py +207 -0
  86. numdaplot/data_types/pandas_mapping.py +114 -0
  87. numdaplot/data_types/time_of_day.py +292 -0
  88. numdaplot/data_types/type.py +224 -0
  89. numdaplot/data_types/value_family.py +149 -0
  90. numdaplot/data_types/value_type.py +147 -0
  91. numdaplot/dates/__init__.py +5 -0
  92. numdaplot/dates/custom_date_format.py +83 -0
  93. numdaplot/dates/date_format.py +120 -0
  94. numdaplot/dates/date_part.py +59 -0
  95. numdaplot/dates/date_part_unit.py +153 -0
  96. numdaplot/dates/date_period.py +57 -0
  97. numdaplot/dates/duration_in.py +58 -0
  98. numdaplot/dates/duration_unit.py +90 -0
  99. numdaplot/dates/period_unit.py +101 -0
  100. numdaplot/dates/time_function.py +56 -0
  101. numdaplot/dates/time_zone.py +68 -0
  102. numdaplot/dates/time_zone_change.py +71 -0
  103. numdaplot/dates/time_zone_mode.py +81 -0
  104. numdaplot/dates/to_duration.py +58 -0
  105. numdaplot/errors/__init__.py +7 -0
  106. numdaplot/errors/broadcast_warning.py +36 -0
  107. numdaplot/errors/calculation_warning.py +35 -0
  108. numdaplot/errors/cell_out_of_range_error.py +77 -0
  109. numdaplot/errors/column_not_found_error.py +64 -0
  110. numdaplot/errors/conflicting_settings_error.py +60 -0
  111. numdaplot/errors/dimension_error.py +62 -0
  112. numdaplot/errors/display_warning.py +32 -0
  113. numdaplot/errors/duplicate_column_error.py +82 -0
  114. numdaplot/errors/duplicate_label_error.py +55 -0
  115. numdaplot/errors/duplicate_statistic_error.py +55 -0
  116. numdaplot/errors/duplicate_value_error.py +54 -0
  117. numdaplot/errors/empty_array_error.py +55 -0
  118. numdaplot/errors/empty_list_error.py +52 -0
  119. numdaplot/errors/empty_region_error.py +34 -0
  120. numdaplot/errors/empty_text_error.py +34 -0
  121. numdaplot/errors/empty_total_error.py +62 -0
  122. numdaplot/errors/empty_values_error.py +34 -0
  123. numdaplot/errors/file_access_error.py +70 -0
  124. numdaplot/errors/file_exists_error.py +62 -0
  125. numdaplot/errors/file_not_found_error.py +56 -0
  126. numdaplot/errors/incompatible_charts_error.py +80 -0
  127. numdaplot/errors/incompatible_types_error.py +104 -0
  128. numdaplot/errors/integer_overflow_error.py +61 -0
  129. numdaplot/errors/invalid_base_error.py +52 -0
  130. numdaplot/errors/invalid_bin_width_error.py +66 -0
  131. numdaplot/errors/invalid_bounds_error.py +58 -0
  132. numdaplot/errors/invalid_chart_data_error.py +81 -0
  133. numdaplot/errors/invalid_color_count_error.py +63 -0
  134. numdaplot/errors/invalid_color_error.py +51 -0
  135. numdaplot/errors/invalid_column_name_error.py +52 -0
  136. numdaplot/errors/invalid_conversion_error.py +119 -0
  137. numdaplot/errors/invalid_count_error.py +61 -0
  138. numdaplot/errors/invalid_date_format_error.py +51 -0
  139. numdaplot/errors/invalid_deviation_error.py +52 -0
  140. numdaplot/errors/invalid_fraction_error.py +51 -0
  141. numdaplot/errors/invalid_label_count_error.py +61 -0
  142. numdaplot/errors/invalid_limits_error.py +111 -0
  143. numdaplot/errors/invalid_opacity_error.py +52 -0
  144. numdaplot/errors/invalid_point_size_error.py +52 -0
  145. numdaplot/errors/invalid_position_error.py +106 -0
  146. numdaplot/errors/invalid_resolution_error.py +51 -0
  147. numdaplot/errors/invalid_rotation_error.py +53 -0
  148. numdaplot/errors/invalid_seed_error.py +53 -0
  149. numdaplot/errors/invalid_separator_error.py +52 -0
  150. numdaplot/errors/invalid_shape_error.py +52 -0
  151. numdaplot/errors/invalid_sheet_name_error.py +54 -0
  152. numdaplot/errors/invalid_size_error.py +58 -0
  153. numdaplot/errors/invalid_step_error.py +77 -0
  154. numdaplot/errors/invalid_suffixes_error.py +61 -0
  155. numdaplot/errors/invalid_time_zone_change_error.py +63 -0
  156. numdaplot/errors/invalid_type_error.py +79 -0
  157. numdaplot/errors/irregular_list_error.py +36 -0
  158. numdaplot/errors/join_relation_error.py +183 -0
  159. numdaplot/errors/missing_dependency_error.py +58 -0
  160. numdaplot/errors/missing_type_error.py +36 -0
  161. numdaplot/errors/missing_value_error.py +62 -0
  162. numdaplot/errors/not_single_value_error.py +53 -0
  163. numdaplot/errors/numdaplot_error.py +25 -0
  164. numdaplot/errors/numdaplot_warning.py +34 -0
  165. numdaplot/errors/occupied_cell_error.py +63 -0
  166. numdaplot/errors/out_of_domain_error.py +70 -0
  167. numdaplot/errors/readability_warning.py +35 -0
  168. numdaplot/errors/refused_operation_error.py +64 -0
  169. numdaplot/errors/refused_setting_error.py +60 -0
  170. numdaplot/errors/rejected_dates.py +60 -0
  171. numdaplot/errors/repeated_key.py +36 -0
  172. numdaplot/errors/shape_mismatch_error.py +67 -0
  173. numdaplot/errors/time_overflow_error.py +131 -0
  174. numdaplot/errors/time_zone_mismatch_error.py +83 -0
  175. numdaplot/errors/unknown_time_zone_error.py +51 -0
  176. numdaplot/errors/unmatched_value_error.py +81 -0
  177. numdaplot/errors/unsupported_image_format_error.py +56 -0
  178. numdaplot/errors/unsupported_index_error.py +38 -0
  179. numdaplot/errors/unsupported_missing_error.py +129 -0
  180. numdaplot/errors/unsupported_type_error.py +62 -0
  181. numdaplot/errors/value_conversion_error.py +215 -0
  182. numdaplot/ordering/__init__.py +5 -0
  183. numdaplot/ordering/missing_position.py +46 -0
  184. numdaplot/ordering/order.py +46 -0
  185. numdaplot/package_version.py +36 -0
  186. numdaplot/plots/__init__.py +5 -0
  187. numdaplot/plots/chart_layer.py +47 -0
  188. numdaplot/plots/charts/__init__.py +5 -0
  189. numdaplot/plots/charts/bar_chart.py +98 -0
  190. numdaplot/plots/charts/bar_layout.py +58 -0
  191. numdaplot/plots/charts/bin_count.py +61 -0
  192. numdaplot/plots/charts/bin_width.py +78 -0
  193. numdaplot/plots/charts/box_chart.py +97 -0
  194. numdaplot/plots/charts/cell_values.py +61 -0
  195. numdaplot/plots/charts/chart.py +59 -0
  196. numdaplot/plots/charts/chart_settings.py +105 -0
  197. numdaplot/plots/charts/color_scale.py +147 -0
  198. numdaplot/plots/charts/heatmap_chart.py +92 -0
  199. numdaplot/plots/charts/histogram_chart.py +93 -0
  200. numdaplot/plots/charts/line_chart.py +100 -0
  201. numdaplot/plots/charts/line_type.py +75 -0
  202. numdaplot/plots/charts/marker_shape.py +113 -0
  203. numdaplot/plots/charts/missing_chart.py +60 -0
  204. numdaplot/plots/charts/missing_map_chart.py +27 -0
  205. numdaplot/plots/charts/orientation.py +58 -0
  206. numdaplot/plots/charts/outliers.py +49 -0
  207. numdaplot/plots/charts/percentages.py +55 -0
  208. numdaplot/plots/charts/pie_chart.py +87 -0
  209. numdaplot/plots/charts/scatter_chart.py +159 -0
  210. numdaplot/plots/charts/value_axis.py +66 -0
  211. numdaplot/plots/data/__init__.py +5 -0
  212. numdaplot/plots/data/array_values.py +128 -0
  213. numdaplot/plots/data/chart_data.py +143 -0
  214. numdaplot/plots/data/chart_values.py +109 -0
  215. numdaplot/plots/data/column_reading.py +468 -0
  216. numdaplot/plots/data/heatmap_values.py +63 -0
  217. numdaplot/plots/data/missing_cells.py +165 -0
  218. numdaplot/plots/data/pie_values.py +215 -0
  219. numdaplot/plots/data/point_values.py +249 -0
  220. numdaplot/plots/data/position_kind.py +83 -0
  221. numdaplot/plots/data/renamed_layers.py +340 -0
  222. numdaplot/plots/data/sample_values.py +160 -0
  223. numdaplot/plots/data/shown_columns.py +248 -0
  224. numdaplot/plots/data/table_values.py +256 -0
  225. numdaplot/plots/data/unique_labels.py +45 -0
  226. numdaplot/plots/drawing/__init__.py +5 -0
  227. numdaplot/plots/drawing/bar_drawing.py +316 -0
  228. numdaplot/plots/drawing/box_drawing.py +344 -0
  229. numdaplot/plots/drawing/cell_merging.py +237 -0
  230. numdaplot/plots/drawing/chart_texts.py +124 -0
  231. numdaplot/plots/drawing/color_bar.py +57 -0
  232. numdaplot/plots/drawing/color_scale_values.py +120 -0
  233. numdaplot/plots/drawing/default_labels.py +41 -0
  234. numdaplot/plots/drawing/drawn_chart.py +50 -0
  235. numdaplot/plots/drawing/grid_axes.py +75 -0
  236. numdaplot/plots/drawing/heatmap_drawing.py +313 -0
  237. numdaplot/plots/drawing/histogram_drawing.py +350 -0
  238. numdaplot/plots/drawing/label_room.py +344 -0
  239. numdaplot/plots/drawing/label_thinning.py +216 -0
  240. numdaplot/plots/drawing/layer_alignment.py +319 -0
  241. numdaplot/plots/drawing/layer_colors.py +123 -0
  242. numdaplot/plots/drawing/line_drawing.py +85 -0
  243. numdaplot/plots/drawing/marker_codes.py +20 -0
  244. numdaplot/plots/drawing/missing_drawing.py +360 -0
  245. numdaplot/plots/drawing/moment_period_formatter.py +253 -0
  246. numdaplot/plots/drawing/pie_drawing.py +185 -0
  247. numdaplot/plots/drawing/plot_axes.py +38 -0
  248. numdaplot/plots/drawing/plot_drawing.py +288 -0
  249. numdaplot/plots/drawing/plot_theme.py +45 -0
  250. numdaplot/plots/drawing/position_axis.py +278 -0
  251. numdaplot/plots/drawing/scatter_drawing.py +364 -0
  252. numdaplot/plots/drawing/series_colors.py +177 -0
  253. numdaplot/plots/drawing/size_inches.py +45 -0
  254. numdaplot/plots/drawing/style_drawing.py +410 -0
  255. numdaplot/plots/drawing/text_contrast.py +44 -0
  256. numdaplot/plots/drawing/tick_rotation.py +354 -0
  257. numdaplot/plots/drawing/time_axis.py +212 -0
  258. numdaplot/plots/drawing/whole_numbers.py +72 -0
  259. numdaplot/plots/figure/__init__.py +5 -0
  260. numdaplot/plots/figure/cell.py +95 -0
  261. numdaplot/plots/figure/figure.py +256 -0
  262. numdaplot/plots/figure/figure_drawing.py +99 -0
  263. numdaplot/plots/figure/figure_style.py +60 -0
  264. numdaplot/plots/figure/layout.py +71 -0
  265. numdaplot/plots/figure/placement.py +150 -0
  266. numdaplot/plots/layer_reading.py +166 -0
  267. numdaplot/plots/output/__init__.py +5 -0
  268. numdaplot/plots/output/image_saving.py +187 -0
  269. numdaplot/plots/output/plot_display.py +181 -0
  270. numdaplot/plots/output/shown_object.py +45 -0
  271. numdaplot/plots/overlay_checks.py +245 -0
  272. numdaplot/plots/plot.py +31 -0
  273. numdaplot/plots/plot_data.py +140 -0
  274. numdaplot/plots/plot_distribution_creation.py +237 -0
  275. numdaplot/plots/plot_output.py +124 -0
  276. numdaplot/plots/plot_overlays.py +273 -0
  277. numdaplot/plots/plot_overview_creation.py +195 -0
  278. numdaplot/plots/plot_series_creation.py +213 -0
  279. numdaplot/plots/style/__init__.py +5 -0
  280. numdaplot/plots/style/axis_settings.py +60 -0
  281. numdaplot/plots/style/color.py +168 -0
  282. numdaplot/plots/style/custom_color.py +65 -0
  283. numdaplot/plots/style/grid_lines.py +49 -0
  284. numdaplot/plots/style/image_options.py +71 -0
  285. numdaplot/plots/style/legend_position.py +149 -0
  286. numdaplot/plots/style/plot_style.py +136 -0
  287. numdaplot/plots/style/size.py +70 -0
  288. numdaplot/plots/style/size_unit.py +62 -0
  289. numdaplot/positions/__init__.py +5 -0
  290. numdaplot/positions/axis.py +54 -0
  291. numdaplot/positions/index.py +51 -0
  292. numdaplot/positions/range.py +90 -0
  293. numdaplot/positions/region.py +92 -0
  294. numdaplot/py.typed +0 -0
  295. numdaplot/ratios/__init__.py +5 -0
  296. numdaplot/ratios/fraction.py +40 -0
  297. numdaplot/ratios/measure.py +48 -0
  298. numdaplot/rules/__init__.py +5 -0
  299. numdaplot/rules/between.py +78 -0
  300. numdaplot/rules/bounds.py +83 -0
  301. numdaplot/rules/case.py +48 -0
  302. numdaplot/rules/contains.py +63 -0
  303. numdaplot/rules/equal.py +43 -0
  304. numdaplot/rules/greater.py +39 -0
  305. numdaplot/rules/greater_or_equal.py +38 -0
  306. numdaplot/rules/is_in.py +67 -0
  307. numdaplot/rules/is_missing.py +25 -0
  308. numdaplot/rules/is_present.py +25 -0
  309. numdaplot/rules/less.py +39 -0
  310. numdaplot/rules/less_or_equal.py +38 -0
  311. numdaplot/rules/not_equal.py +45 -0
  312. numdaplot/rules/rule.py +62 -0
  313. numdaplot/rules/rule_values.py +44 -0
  314. numdaplot/rules/value_rule.py +110 -0
  315. numdaplot/settings/__init__.py +5 -0
  316. numdaplot/settings/argument_types.py +327 -0
  317. numdaplot/settings/field_types.py +593 -0
  318. numdaplot/statistics/__init__.py +5 -0
  319. numdaplot/statistics/count.py +71 -0
  320. numdaplot/statistics/count_distinct.py +27 -0
  321. numdaplot/statistics/counted_missing.py +46 -0
  322. numdaplot/statistics/maximum.py +27 -0
  323. numdaplot/statistics/mean.py +27 -0
  324. numdaplot/statistics/median.py +27 -0
  325. numdaplot/statistics/minimum.py +27 -0
  326. numdaplot/statistics/most_frequent.py +27 -0
  327. numdaplot/statistics/most_frequent_count.py +27 -0
  328. numdaplot/statistics/quantile.py +61 -0
  329. numdaplot/statistics/standard_deviation.py +29 -0
  330. numdaplot/statistics/statistic.py +63 -0
  331. numdaplot/statistics/sum.py +27 -0
  332. numdaplot/tables/__init__.py +5 -0
  333. numdaplot/tables/aggregation/__init__.py +5 -0
  334. numdaplot/tables/aggregation/aggregated_frame.py +189 -0
  335. numdaplot/tables/aggregation/aggregation.py +97 -0
  336. numdaplot/tables/aggregation/calculation.py +123 -0
  337. numdaplot/tables/aggregation/result_column.py +108 -0
  338. numdaplot/tables/aggregation/row_groups.py +96 -0
  339. numdaplot/tables/aggregation/statistic_name.py +122 -0
  340. numdaplot/tables/columns/__init__.py +5 -0
  341. numdaplot/tables/columns/added_column.py +89 -0
  342. numdaplot/tables/columns/boolean_conversion.py +144 -0
  343. numdaplot/tables/columns/boolean_rule.py +59 -0
  344. numdaplot/tables/columns/bracket_end.py +50 -0
  345. numdaplot/tables/columns/bracket_names.py +346 -0
  346. numdaplot/tables/columns/bracketed_column.py +179 -0
  347. numdaplot/tables/columns/brackets.py +234 -0
  348. numdaplot/tables/columns/chosen_columns.py +55 -0
  349. numdaplot/tables/columns/column_choice.py +84 -0
  350. numdaplot/tables/columns/column_mode.py +64 -0
  351. numdaplot/tables/columns/column_names.py +186 -0
  352. numdaplot/tables/columns/conversion.py +103 -0
  353. numdaplot/tables/columns/converted_column.py +669 -0
  354. numdaplot/tables/columns/date_conversion.py +526 -0
  355. numdaplot/tables/columns/date_range.py +135 -0
  356. numdaplot/tables/columns/name_change.py +67 -0
  357. numdaplot/tables/columns/new_column.py +79 -0
  358. numdaplot/tables/columns/number_conversion.py +281 -0
  359. numdaplot/tables/columns/renamed_columns.py +60 -0
  360. numdaplot/tables/columns/renaming.py +81 -0
  361. numdaplot/tables/columns/text_conversion.py +70 -0
  362. numdaplot/tables/columns/time_conversion.py +313 -0
  363. numdaplot/tables/columns/time_zone_conversion.py +128 -0
  364. numdaplot/tables/conflict.py +68 -0
  365. numdaplot/tables/description/__init__.py +5 -0
  366. numdaplot/tables/description/described_frame.py +335 -0
  367. numdaplot/tables/description/description.py +155 -0
  368. numdaplot/tables/duplicates/__init__.py +5 -0
  369. numdaplot/tables/duplicates/deduplicated_frame.py +66 -0
  370. numdaplot/tables/duplicates/deduplication.py +88 -0
  371. numdaplot/tables/duplicates/keep.py +81 -0
  372. numdaplot/tables/files/__init__.py +5 -0
  373. numdaplot/tables/files/column_names.py +60 -0
  374. numdaplot/tables/files/csv_file.py +265 -0
  375. numdaplot/tables/files/csv_read_options.py +89 -0
  376. numdaplot/tables/files/csv_separator.py +41 -0
  377. numdaplot/tables/files/csv_write_options.py +79 -0
  378. numdaplot/tables/files/decimal_count.py +42 -0
  379. numdaplot/tables/files/encoding.py +82 -0
  380. numdaplot/tables/files/excel_file.py +171 -0
  381. numdaplot/tables/files/excel_read_options.py +79 -0
  382. numdaplot/tables/files/excel_sheet.py +50 -0
  383. numdaplot/tables/files/excel_time_cells.py +146 -0
  384. numdaplot/tables/files/excel_write_options.py +63 -0
  385. numdaplot/tables/files/file_access.py +152 -0
  386. numdaplot/tables/files/file_paths.py +106 -0
  387. numdaplot/tables/files/json_decimals.py +387 -0
  388. numdaplot/tables/files/json_file.py +203 -0
  389. numdaplot/tables/files/json_layout.py +63 -0
  390. numdaplot/tables/files/json_read_options.py +64 -0
  391. numdaplot/tables/files/json_write_options.py +71 -0
  392. numdaplot/tables/files/missing_texts.py +63 -0
  393. numdaplot/tables/files/optional_package.py +42 -0
  394. numdaplot/tables/files/pandas_backend.py +11 -0
  395. numdaplot/tables/files/parquet_file.py +91 -0
  396. numdaplot/tables/files/parquet_read_options.py +56 -0
  397. numdaplot/tables/files/sas_file.py +94 -0
  398. numdaplot/tables/files/sas_read_options.py +67 -0
  399. numdaplot/tables/files/stata_file.py +83 -0
  400. numdaplot/tables/files/stata_read_options.py +56 -0
  401. numdaplot/tables/files/xpt_read_options.py +65 -0
  402. numdaplot/tables/filtering/__init__.py +5 -0
  403. numdaplot/tables/filtering/checked_frame.py +60 -0
  404. numdaplot/tables/filtering/column_mask.py +71 -0
  405. numdaplot/tables/filtering/column_match.py +62 -0
  406. numdaplot/tables/filtering/condition.py +94 -0
  407. numdaplot/tables/filtering/filter.py +74 -0
  408. numdaplot/tables/filtering/filter_mode.py +67 -0
  409. numdaplot/tables/filtering/row_mask.py +152 -0
  410. numdaplot/tables/filtering/rule_moments.py +164 -0
  411. numdaplot/tables/frames/__init__.py +5 -0
  412. numdaplot/tables/frames/array_frame.py +95 -0
  413. numdaplot/tables/frames/cleaned_names.py +132 -0
  414. numdaplot/tables/frames/column.py +15 -0
  415. numdaplot/tables/frames/column_values.py +273 -0
  416. numdaplot/tables/frames/frame_equality.py +130 -0
  417. numdaplot/tables/frames/frame_normalization.py +459 -0
  418. numdaplot/tables/frames/named_column_errors.py +85 -0
  419. numdaplot/tables/frames/pandas_decimals.py +113 -0
  420. numdaplot/tables/frames/region_positions.py +113 -0
  421. numdaplot/tables/frames/table_text.py +222 -0
  422. numdaplot/tables/frames/time_columns.py +345 -0
  423. numdaplot/tables/frames/time_range_errors.py +117 -0
  424. numdaplot/tables/frames/time_zones.py +271 -0
  425. numdaplot/tables/joining/__init__.py +5 -0
  426. numdaplot/tables/joining/join.py +110 -0
  427. numdaplot/tables/joining/join_keys.py +367 -0
  428. numdaplot/tables/joining/join_mode.py +93 -0
  429. numdaplot/tables/joining/join_relation.py +149 -0
  430. numdaplot/tables/joining/join_suffixes.py +71 -0
  431. numdaplot/tables/joining/joined_frame.py +166 -0
  432. numdaplot/tables/joining/joined_names.py +107 -0
  433. numdaplot/tables/joining/joined_rows.py +235 -0
  434. numdaplot/tables/joining/key_types.py +57 -0
  435. numdaplot/tables/joining/relation.py +78 -0
  436. numdaplot/tables/missing/__init__.py +5 -0
  437. numdaplot/tables/missing/missing_count.py +59 -0
  438. numdaplot/tables/missing/missing_counts.py +214 -0
  439. numdaplot/tables/missing/missing_drop.py +98 -0
  440. numdaplot/tables/missing/missing_mode.py +63 -0
  441. numdaplot/tables/missing/missing_ratio.py +71 -0
  442. numdaplot/tables/missing/missing_removal.py +257 -0
  443. numdaplot/tables/missing/missing_summary.py +174 -0
  444. numdaplot/tables/missing/ratio_comparison.py +70 -0
  445. numdaplot/tables/pivot/__init__.py +5 -0
  446. numdaplot/tables/pivot/pivot_table.py +104 -0
  447. numdaplot/tables/pivot/pivoted_frame.py +244 -0
  448. numdaplot/tables/preview/__init__.py +5 -0
  449. numdaplot/tables/preview/notebook_display.py +238 -0
  450. numdaplot/tables/preview/preview.py +100 -0
  451. numdaplot/tables/preview/preview_rows.py +55 -0
  452. numdaplot/tables/preview/shown_columns.py +62 -0
  453. numdaplot/tables/preview/side.py +82 -0
  454. numdaplot/tables/sorting/__init__.py +5 -0
  455. numdaplot/tables/sorting/sort_key.py +71 -0
  456. numdaplot/tables/sorting/sorted_frame.py +81 -0
  457. numdaplot/tables/sorting/sorting.py +82 -0
  458. numdaplot/tables/table.py +71 -0
  459. numdaplot/tables/table_calculation.py +172 -0
  460. numdaplot/tables/table_columns.py +214 -0
  461. numdaplot/tables/table_conversion.py +351 -0
  462. numdaplot/tables/table_data.py +321 -0
  463. numdaplot/tables/table_display.py +56 -0
  464. numdaplot/tables/table_joining.py +80 -0
  465. numdaplot/tables/table_layout.py +105 -0
  466. numdaplot/tables/table_missing.py +146 -0
  467. numdaplot/tables/table_reading.py +451 -0
  468. numdaplot/tables/table_refusals.py +295 -0
  469. numdaplot/tables/table_selection.py +163 -0
  470. numdaplot/tables/table_writing.py +269 -0
  471. numdaplot-0.1.0.dist-info/METADATA +176 -0
  472. numdaplot-0.1.0.dist-info/RECORD +474 -0
  473. numdaplot-0.1.0.dist-info/WHEEL +4 -0
  474. numdaplot-0.1.0.dist-info/licenses/LICENSE +28 -0
@@ -0,0 +1,335 @@
1
+ """
2
+ Description of the columns of a Table.
3
+
4
+ .. versionadded:: 0.1.0
5
+ """
6
+
7
+ from datetime import UTC, datetime
8
+ from typing import Any
9
+ from zoneinfo import ZoneInfo
10
+
11
+ import numpy
12
+ import pandas
13
+ from numpy.typing import NDArray
14
+
15
+ from numdaplot.arrays.conversion.python_values import to_python_list
16
+ from numdaplot.data_types.numpy_mapping import from_numpy_dtype, to_numpy_dtype
17
+ from numdaplot.data_types.type import Type
18
+ from numdaplot.data_types.value_family import ValueFamily, find_family
19
+ from numdaplot.dates.time_zone import TimeZone
20
+ from numdaplot.errors.duplicate_column_error import DuplicateColumnError
21
+ from numdaplot.errors.incompatible_types_error import IncompatibleTypesError
22
+ from numdaplot.statistics.statistic import Statistic
23
+ from numdaplot.tables.aggregation.result_column import build_result_column, compute_cell
24
+ from numdaplot.tables.aggregation.statistic_name import name_statistic
25
+ from numdaplot.tables.columns.column_names import require_known_columns
26
+ from numdaplot.tables.description.description import DEFAULT_FUNCTIONS, Description
27
+ from numdaplot.tables.frames.column import Column
28
+ from numdaplot.tables.frames.column_values import build_column, find_column_type, read_present_values
29
+ from numdaplot.tables.frames.time_zones import attribute_source_time_zone, find_column_time_zone
30
+
31
+ STATISTIC_COLUMN_NAME = "statistic"
32
+ SINGLE_FAMILY_COUNT = 1
33
+
34
+
35
+ def describe_frame(frame: pandas.DataFrame, description: Description) -> pandas.DataFrame:
36
+ """
37
+ Return statistics of columns of a Table, one row per statistic and one column per described column.
38
+
39
+ .. versionadded:: 0.1.0
40
+
41
+ Parameters
42
+ ----------
43
+ frame
44
+ The columns of a Table.
45
+ description
46
+ The statistics and the columns to describe.
47
+
48
+ Returns
49
+ -------
50
+ pandas.DataFrame
51
+ A first ``statistic`` column naming each statistic, then one column per described column.
52
+ A cell is missing when the statistic does not apply to the column or finds no value.
53
+
54
+ Raises
55
+ ------
56
+ ColumnNotFoundError
57
+ When a described column does not exist.
58
+ DuplicateColumnError
59
+ When a described column is named ``statistic``.
60
+
61
+ Examples
62
+ --------
63
+ >>> import pandas
64
+ >>> import numdaplot as ndp
65
+ >>> from numdaplot.tables.description.described_frame import describe_frame
66
+ >>> frame = pandas.DataFrame({"price": [1.0, 3.0]})
67
+ >>> describe_frame(frame, ndp.Description(functions=[ndp.Count(), ndp.Mean()]))
68
+ statistic price
69
+ 0 count_excluded 2.0
70
+ 1 mean 2.0
71
+ """
72
+ functions = list[Statistic](DEFAULT_FUNCTIONS)
73
+ if description.functions is not None:
74
+ functions = description.functions
75
+
76
+ described_names = find_described_columns(frame, description)
77
+ statistic_names = [name_statistic(function) for function in functions]
78
+ text_dtype = to_numpy_dtype(Type.TEXT)
79
+ statistic_values = numpy.array(statistic_names, dtype=text_dtype)
80
+ statistic_column = build_column(statistic_values)
81
+ described_columns = {STATISTIC_COLUMN_NAME: statistic_column}
82
+
83
+ for column_name in described_names:
84
+ column = frame[column_name]
85
+ described_column = describe_column(column, functions)
86
+ described_columns[column_name] = described_column
87
+
88
+ function_count = len(functions)
89
+ row_numbers = pandas.RangeIndex(function_count)
90
+ described_frame = pandas.DataFrame(described_columns, index=row_numbers)
91
+
92
+ return described_frame
93
+
94
+
95
+ def find_described_columns(frame: pandas.DataFrame, description: Description) -> list[str]:
96
+ """
97
+ Return the names of the columns to describe.
98
+
99
+ .. versionadded:: 0.1.0
100
+
101
+ Parameters
102
+ ----------
103
+ frame
104
+ The columns of a Table.
105
+ description
106
+ The settings of the description.
107
+
108
+ Returns
109
+ -------
110
+ list[str]
111
+ The given names, or every number column in the order of the Table.
112
+
113
+ Raises
114
+ ------
115
+ ColumnNotFoundError
116
+ When a given column does not exist.
117
+ DuplicateColumnError
118
+ When a described column is named ``statistic``.
119
+
120
+ Examples
121
+ --------
122
+ >>> import pandas
123
+ >>> import numdaplot as ndp
124
+ >>> from numdaplot.tables.description.described_frame import find_described_columns
125
+ >>> frame = pandas.DataFrame({"city": pandas.array(["Pau"], dtype="string"), "price": [1.5]})
126
+ >>> find_described_columns(frame, ndp.Description())
127
+ ['price']
128
+ """
129
+ column_names = [str(column_name) for column_name in frame.columns]
130
+ described_names = list[str]()
131
+ if description.columns is not None:
132
+ require_known_columns(description.columns, column_names)
133
+ described_names = description.columns
134
+ else:
135
+ described_names = find_number_columns(frame)
136
+
137
+ if STATISTIC_COLUMN_NAME in described_names:
138
+ raise DuplicateColumnError(STATISTIC_COLUMN_NAME)
139
+
140
+ return described_names
141
+
142
+
143
+ def find_number_columns(frame: pandas.DataFrame) -> list[str]:
144
+ """
145
+ Return the names of the columns holding numbers.
146
+
147
+ .. versionadded:: 0.1.0
148
+
149
+ Parameters
150
+ ----------
151
+ frame
152
+ The columns of a Table.
153
+
154
+ Returns
155
+ -------
156
+ list[str]
157
+ The names of the integer and decimal columns, in order.
158
+
159
+ Examples
160
+ --------
161
+ >>> import pandas
162
+ >>> from numdaplot.tables.description.described_frame import find_number_columns
163
+ >>> find_number_columns(pandas.DataFrame({"price": [1.5], "paid": pandas.array([True], dtype="boolean")}))
164
+ ['price']
165
+ """
166
+ number_names = list[str]()
167
+
168
+ for column_name in frame.columns:
169
+ column = frame[column_name]
170
+ column_type = find_column_type(column)
171
+ column_family = find_family(column_type)
172
+ if column_family == ValueFamily.NUMBER:
173
+ number_name = str(column_name)
174
+ number_names.append(number_name)
175
+
176
+ return number_names
177
+
178
+
179
+ def describe_column(column: Column, functions: list[Statistic]) -> Column:
180
+ """
181
+ Return the statistics of one column, missing where a statistic does not apply or finds no value.
182
+
183
+ .. versionadded:: 0.1.0
184
+
185
+ Parameters
186
+ ----------
187
+ column
188
+ A Table column.
189
+ functions
190
+ The statistics, one result each.
191
+
192
+ Returns
193
+ -------
194
+ Column
195
+ One result per statistic. When the results mix kinds of values, such as a count and a text,
196
+ every result is written as a text.
197
+
198
+ Examples
199
+ --------
200
+ >>> import pandas
201
+ >>> import numdaplot as ndp
202
+ >>> from numdaplot.tables.description.described_frame import describe_column
203
+ >>> describe_column(pandas.Series(["b", "a"], dtype="string"), [ndp.Count(), ndp.Min(), ndp.Mean()]).tolist()
204
+ ['2', 'a', <NA>]
205
+ """
206
+ present_values = read_present_values(column)
207
+ value_count = len(column)
208
+ results = [compute_description_cell(present_values, function, value_count) for function in functions]
209
+ present_results = [result for result in results if result is not None]
210
+ result_families = {find_result_family(result) for result in present_results}
211
+ family_count = len(result_families)
212
+ time_zone = find_column_time_zone(column)
213
+ if family_count > SINGLE_FAMILY_COUNT:
214
+ results = [convert_result_to_text(result, time_zone) for result in results]
215
+
216
+ utc_column = build_result_column(results)
217
+ described_column = attribute_source_time_zone(utc_column, column)
218
+
219
+ return described_column
220
+
221
+
222
+ def compute_description_cell(
223
+ present_values: NDArray[Any],
224
+ statistic: Statistic,
225
+ value_count: int,
226
+ ) -> NDArray[Any] | None:
227
+ """
228
+ Return a statistic of present values, or nothing when it does not apply or finds no value.
229
+
230
+ .. versionadded:: 0.1.0
231
+
232
+ Parameters
233
+ ----------
234
+ present_values
235
+ One-dimensional values without missing value.
236
+ statistic
237
+ Any statistic of numdaplot.
238
+ value_count
239
+ The number of values before the missing ones were left out.
240
+
241
+ Returns
242
+ -------
243
+ NDArray or None
244
+ The result as a one-value array, or ``None``.
245
+
246
+ Examples
247
+ --------
248
+ >>> import numpy
249
+ >>> import numdaplot as ndp
250
+ >>> from numdaplot.tables.description.described_frame import compute_description_cell
251
+ >>> texts = numpy.array(["b", "a"], dtype="T")
252
+ >>> compute_description_cell(texts, ndp.Min(), 2)
253
+ array(['a'], dtype=StringDType(na_object=nan))
254
+ >>> print(compute_description_cell(texts, ndp.Mean(), 2))
255
+ None
256
+ """
257
+ try:
258
+ result = compute_cell(present_values, statistic, value_count)
259
+ except IncompatibleTypesError:
260
+ return None
261
+
262
+ return result
263
+
264
+
265
+ def find_result_family(result: NDArray[Any]) -> ValueFamily:
266
+ """
267
+ Return the family of the type of a result.
268
+
269
+ .. versionadded:: 0.1.0
270
+
271
+ Parameters
272
+ ----------
273
+ result
274
+ A one-value array.
275
+
276
+ Returns
277
+ -------
278
+ ValueFamily
279
+ The family of its type.
280
+
281
+ Examples
282
+ --------
283
+ >>> import numpy
284
+ >>> from numdaplot.tables.description.described_frame import find_result_family
285
+ >>> find_result_family(numpy.array([2]))
286
+ <ValueFamily.NUMBER: 1>
287
+ """
288
+ result_type = from_numpy_dtype(result.dtype)
289
+ result_family = find_family(result_type)
290
+
291
+ return result_family
292
+
293
+
294
+ def convert_result_to_text(result: NDArray[Any] | None, time_zone: TimeZone | None) -> NDArray[Any] | None:
295
+ """
296
+ Return a result written as a text.
297
+
298
+ .. versionadded:: 0.1.0
299
+
300
+ Parameters
301
+ ----------
302
+ result
303
+ A one-value array, or ``None``.
304
+ time_zone
305
+ The time zone of the described column: a datetime result, computed as a UTC clock time, is written
306
+ in this zone with its offset. ``None`` when the column has no zone.
307
+
308
+ Returns
309
+ -------
310
+ NDArray or None
311
+ A one-text array, or ``None`` when there is no result.
312
+
313
+ Examples
314
+ --------
315
+ >>> import numpy
316
+ >>> from numdaplot.tables.description.described_frame import convert_result_to_text
317
+ >>> convert_result_to_text(numpy.array([2]), None)
318
+ array(['2'], dtype=StringDType(na_object=nan))
319
+ """
320
+ if result is None:
321
+ return None
322
+
323
+ python_values = to_python_list(result)
324
+ single_value = python_values[0]
325
+ shown_value = single_value
326
+ if time_zone is not None and isinstance(single_value, datetime):
327
+ utc_datetime = single_value.replace(tzinfo=UTC)
328
+ zone_info = ZoneInfo(time_zone.name)
329
+ shown_value = utc_datetime.astimezone(zone_info)
330
+
331
+ result_text = str(shown_value)
332
+ text_dtype = to_numpy_dtype(Type.TEXT)
333
+ text_result = numpy.array([result_text], dtype=text_dtype)
334
+
335
+ return text_result
@@ -0,0 +1,155 @@
1
+ """
2
+ Settings of the description of the columns of a Table.
3
+
4
+ .. versionadded:: 0.1.0
5
+ """
6
+
7
+ from dataclasses import dataclass
8
+
9
+ from numdaplot.errors.duplicate_statistic_error import DuplicateStatisticError
10
+ from numdaplot.errors.empty_list_error import EmptyListError
11
+ from numdaplot.settings.field_types import require_field_types
12
+ from numdaplot.statistics.count import Count
13
+ from numdaplot.statistics.maximum import Max
14
+ from numdaplot.statistics.mean import Mean
15
+ from numdaplot.statistics.median import Median
16
+ from numdaplot.statistics.minimum import Min
17
+ from numdaplot.statistics.quantile import Quantile
18
+ from numdaplot.statistics.standard_deviation import StandardDeviation
19
+ from numdaplot.statistics.statistic import Statistic
20
+ from numdaplot.tables.columns.column_names import require_column_names
21
+
22
+ LOWER_QUARTILE = 0.25
23
+ UPPER_QUARTILE = 0.75
24
+ DEFAULT_FUNCTIONS = (
25
+ Count(),
26
+ Mean(),
27
+ StandardDeviation(),
28
+ Min(),
29
+ Quantile(LOWER_QUARTILE),
30
+ Median(),
31
+ Quantile(UPPER_QUARTILE),
32
+ Max(),
33
+ )
34
+ FUNCTION_ITEM_NAME = "function"
35
+ COLUMN_ITEM_NAME = "column"
36
+
37
+
38
+ @dataclass(frozen=True)
39
+ class Description:
40
+ """
41
+ Statistics describing columns of a Table, used by ``Table.describe``.
42
+
43
+ .. versionadded:: 0.1.0
44
+
45
+ Parameters
46
+ ----------
47
+ functions
48
+ The ``Statistic`` objects, one row each, such as ``[ndp.Min(), ndp.Quantile(0.9)]``: see ``Statistic``
49
+ for every statistic. When omitted: ``Count``, ``Mean``, ``StandardDeviation``, ``Min``,
50
+ ``Quantile(0.25)``, ``Median``, ``Quantile(0.75)`` and ``Max``, as in pandas.
51
+ columns
52
+ The names of the columns to describe, one result column each. Every number column when omitted.
53
+
54
+ Raises
55
+ ------
56
+ InvalidTypeError
57
+ When a setting is not of the type its annotation names.
58
+ EmptyListError
59
+ When ``functions`` or ``columns`` is an empty list.
60
+ InvalidColumnNameError
61
+ When a column name is an empty text.
62
+ DuplicateColumnError
63
+ When a column name appears twice.
64
+ DuplicateStatisticError
65
+ When a statistic appears twice in ``functions``.
66
+
67
+ Examples
68
+ --------
69
+ >>> import numdaplot as ndp
70
+ >>> cities = ndp.Array.from_list(["Paris", "Lyon", "Paris"])
71
+ >>> prices = ndp.Array.from_list([120.0, 80.0, 150.0])
72
+ >>> sales = ndp.Table.from_arrays({"city": cities, "price": prices})
73
+ >>> sales.describe(ndp.Description(functions=[ndp.Min(), ndp.Mean(), ndp.Max()]))
74
+ statistic price
75
+ TEXT FLOAT64
76
+ 0 min 80.000000
77
+ 1 mean 116.666667
78
+ 2 max 150.000000
79
+ """
80
+
81
+ functions: list[Statistic] | None = None
82
+ columns: list[str] | None = None
83
+
84
+ def __post_init__(self) -> None:
85
+ """
86
+ Check the lists and replace them with copies that only the description holds.
87
+
88
+ .. versionadded:: 0.1.0
89
+
90
+ Raises
91
+ ------
92
+ InvalidTypeError
93
+ When a setting is not of the type its annotation names.
94
+ EmptyListError
95
+ When ``functions`` or ``columns`` is an empty list.
96
+ InvalidColumnNameError
97
+ When a column name is an empty text.
98
+ DuplicateColumnError
99
+ When a column name appears twice.
100
+ DuplicateStatisticError
101
+ When a statistic appears twice in ``functions``.
102
+ """
103
+ require_field_types(self)
104
+
105
+ if self.functions == []:
106
+ raise EmptyListError(FUNCTION_ITEM_NAME)
107
+
108
+ if self.columns == []:
109
+ raise EmptyListError(COLUMN_ITEM_NAME)
110
+
111
+ if self.functions is not None:
112
+ require_distinct_statistics(self.functions)
113
+ functions_copy = list(self.functions)
114
+ object.__setattr__(self, "functions", functions_copy)
115
+
116
+ if self.columns is not None:
117
+ require_column_names(self.columns)
118
+ columns_copy = list(self.columns)
119
+ object.__setattr__(self, "columns", columns_copy)
120
+
121
+
122
+ def require_distinct_statistics(functions: list[Statistic]) -> None:
123
+ """
124
+ Check that each statistic of a description is given once.
125
+
126
+ .. versionadded:: 0.1.0
127
+
128
+ Parameters
129
+ ----------
130
+ functions
131
+ The statistics of the description.
132
+
133
+ Raises
134
+ ------
135
+ DuplicateStatisticError
136
+ When a statistic appears twice, with the same settings.
137
+
138
+ Examples
139
+ --------
140
+ >>> import numdaplot as ndp
141
+ >>> from numdaplot.tables.description.description import require_distinct_statistics
142
+ >>> require_distinct_statistics([ndp.Quantile(0.25), ndp.Quantile(0.75)])
143
+ >>> try:
144
+ ... require_distinct_statistics([ndp.Mean(), ndp.Mean()])
145
+ ... except ndp.DuplicateStatisticError as error:
146
+ ... print(error)
147
+ The statistic Mean() appears more than once.
148
+ """
149
+ seen_statistics = set[Statistic]()
150
+
151
+ for function in functions:
152
+ if function in seen_statistics:
153
+ raise DuplicateStatisticError(function)
154
+
155
+ seen_statistics.add(function)
@@ -0,0 +1,5 @@
1
+ """
2
+ Removal of the duplicated rows of a Table.
3
+
4
+ .. versionadded:: 0.1.0
5
+ """
@@ -0,0 +1,66 @@
1
+ """
2
+ Removal of the duplicated rows of a Table.
3
+
4
+ .. versionadded:: 0.1.0
5
+ """
6
+
7
+ from typing import Literal
8
+
9
+ import pandas
10
+
11
+ from numdaplot.tables.columns.column_names import require_known_columns
12
+ from numdaplot.tables.duplicates.deduplication import Deduplication
13
+ from numdaplot.tables.duplicates.keep import Keep
14
+
15
+ KEPT_ROWS = dict[Keep, Literal["first", "last", False]](
16
+ {
17
+ Keep.FIRST: "first",
18
+ Keep.LAST: "last",
19
+ Keep.NONE: False,
20
+ }
21
+ )
22
+
23
+
24
+ def drop_duplicate_rows(frame: pandas.DataFrame, deduplication: Deduplication) -> pandas.DataFrame:
25
+ """
26
+ Return the rows of a Table without its duplicated rows.
27
+
28
+ .. versionadded:: 0.1.0
29
+
30
+ Parameters
31
+ ----------
32
+ frame
33
+ The columns of a Table.
34
+ deduplication
35
+ The compared columns and the row kept in each group of duplicates.
36
+
37
+ Returns
38
+ -------
39
+ pandas.DataFrame
40
+ The remaining rows, in their order, numbered from 0.
41
+
42
+ Raises
43
+ ------
44
+ ColumnNotFoundError
45
+ When a compared column does not exist.
46
+
47
+ Examples
48
+ --------
49
+ >>> import pandas
50
+ >>> import numdaplot as ndp
51
+ >>> from numdaplot.tables.duplicates.deduplicated_frame import drop_duplicate_rows
52
+ >>> frame = pandas.DataFrame({"email": ["a@x.fr", "b@x.fr", "a@x.fr"], "visit": [1, 2, 3]})
53
+ >>> drop_duplicate_rows(frame, ndp.Deduplication(columns=["email"], keep=ndp.Keep.LAST))
54
+ email visit
55
+ 0 b@x.fr 2
56
+ 1 a@x.fr 3
57
+ """
58
+ if deduplication.columns is not None:
59
+ column_names = [str(column_name) for column_name in frame.columns]
60
+ require_known_columns(deduplication.columns, column_names)
61
+
62
+ kept_rows = KEPT_ROWS[deduplication.keep]
63
+ remaining_frame = frame.drop_duplicates(subset=deduplication.columns, keep=kept_rows)
64
+ numbered_frame = remaining_frame.reset_index(drop=True)
65
+
66
+ return numbered_frame
@@ -0,0 +1,88 @@
1
+ """
2
+ Settings of the removal of duplicated rows of a Table.
3
+
4
+ .. versionadded:: 0.1.0
5
+ """
6
+
7
+ from dataclasses import dataclass
8
+
9
+ from numdaplot.errors.empty_list_error import EmptyListError
10
+ from numdaplot.settings.field_types import require_field_types
11
+ from numdaplot.tables.columns.column_names import require_column_names
12
+ from numdaplot.tables.duplicates.keep import Keep
13
+
14
+ COLUMN_ITEM_NAME = "column"
15
+
16
+
17
+ @dataclass(frozen=True)
18
+ class Deduplication:
19
+ """
20
+ Which rows count as duplicates and which one is kept, used by ``Table.drop_duplicates``.
21
+
22
+ Two missing values are equal when comparing rows.
23
+
24
+ .. versionadded:: 0.1.0
25
+
26
+ Parameters
27
+ ----------
28
+ columns
29
+ The names of the columns compared, every column when omitted.
30
+ The deduplication keeps its own copy of the list.
31
+ keep
32
+ The row kept in each group of duplicates, the first one by default.
33
+
34
+ Raises
35
+ ------
36
+ InvalidTypeError
37
+ When a setting is not of the type its annotation names.
38
+ EmptyListError
39
+ When ``columns`` is an empty list.
40
+ InvalidColumnNameError
41
+ When a column name is an empty text.
42
+ DuplicateColumnError
43
+ When a column name appears twice.
44
+
45
+ Examples
46
+ --------
47
+ >>> import numdaplot as ndp
48
+ >>> cities = ndp.Array.from_list(["Paris", "Lyon", "Paris"])
49
+ >>> prices = ndp.Array.from_list([120.0, 80.0, 150.0])
50
+ >>> sales = ndp.Table.from_arrays({"city": cities, "price": prices})
51
+ >>> sales.drop_duplicates(ndp.Deduplication(columns=["city"]))
52
+ city price
53
+ TEXT FLOAT64
54
+ 0 Paris 120.0
55
+ 1 Lyon 80.0
56
+ """
57
+
58
+ columns: list[str] | None = None
59
+ keep: Keep = Keep.FIRST
60
+
61
+ def __post_init__(self) -> None:
62
+ """
63
+ Check the columns and replace them with a copy that only the deduplication holds.
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
+ EmptyListError
72
+ When ``columns`` is an empty list.
73
+ InvalidColumnNameError
74
+ When a column name is an empty text.
75
+ DuplicateColumnError
76
+ When a column name appears twice.
77
+ """
78
+ require_field_types(self)
79
+
80
+ if self.columns is None:
81
+ return
82
+
83
+ if self.columns == []:
84
+ raise EmptyListError(COLUMN_ITEM_NAME)
85
+
86
+ require_column_names(self.columns)
87
+ columns_copy = list(self.columns)
88
+ object.__setattr__(self, "columns", columns_copy)