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,59 @@
1
+ """
2
+ How a Conversion reads numbers as booleans.
3
+
4
+ .. versionadded:: 0.1.0
5
+ """
6
+
7
+ from enum import Enum, auto
8
+
9
+
10
+ class BooleanRule(Enum):
11
+ """
12
+ How a ``Conversion`` of a number column to ``BOOL`` reads each number.
13
+
14
+ .. versionadded:: 0.1.0
15
+
16
+ Examples
17
+ --------
18
+ >>> import numdaplot as ndp
19
+ >>> visits = ndp.Table.from_arrays({"visits": ndp.Array.from_list([0, 3])})
20
+ >>> rule = ndp.BooleanRule.NONZERO_TRUE
21
+ >>> visits.convert(ndp.Conversion(column="visits", dtype=ndp.Type.BOOL, booleans=rule))
22
+ visits
23
+ BOOL
24
+ 0 False
25
+ 1 True
26
+ """
27
+
28
+ ZERO_ONE = auto()
29
+ """
30
+ 0 gives ``False`` and 1 gives ``True``; any other number raises ``ValueConversionError``. Used when ``booleans``
31
+ is omitted.
32
+
33
+ Examples
34
+ --------
35
+ >>> import numdaplot as ndp
36
+ >>> severe = ndp.Table.from_arrays({"severe": ndp.Array.from_list([1, 0])})
37
+ >>> severe.convert(ndp.Conversion(column="severe", dtype=ndp.Type.BOOL, booleans=ndp.BooleanRule.ZERO_ONE))
38
+ severe
39
+ BOOL
40
+ 0 True
41
+ 1 False
42
+ """
43
+
44
+ NONZERO_TRUE = auto()
45
+ """
46
+ 0 gives ``False`` and any other number gives ``True``, as in Python.
47
+
48
+ Examples
49
+ --------
50
+ >>> import numdaplot as ndp
51
+ >>> visits = ndp.Table.from_arrays({"visits": ndp.Array.from_list([0, 3, -1])})
52
+ >>> rule = ndp.BooleanRule.NONZERO_TRUE
53
+ >>> visits.convert(ndp.Conversion(column="visits", dtype=ndp.Type.BOOL, booleans=rule))
54
+ visits
55
+ BOOL
56
+ 0 False
57
+ 1 True
58
+ 2 True
59
+ """
@@ -0,0 +1,50 @@
1
+ """
2
+ Whether the first or the last bracket of Brackets has a limit.
3
+
4
+ .. versionadded:: 0.1.0
5
+ """
6
+
7
+ from enum import Enum, auto
8
+
9
+
10
+ class BracketEnd(Enum):
11
+ """
12
+ Whether the first or the last bracket of ``Brackets`` stops at a limit or holds every value beyond it.
13
+
14
+ .. versionadded:: 0.1.0
15
+
16
+ Examples
17
+ --------
18
+ >>> import numdaplot as ndp
19
+ >>> ages = ndp.Table.from_arrays({"age": ndp.Array.from_list([4, 30, 92])})
20
+ >>> brackets = ndp.Brackets(limits=[0, 18, 65], last=ndp.BracketEnd.OPEN)
21
+ >>> ages.convert(ndp.Conversion(column="age", dtype=ndp.Type.CATEGORY, format=brackets)).column("age").to_list()
22
+ ['0 to 17', '18 to 64', '65 or more']
23
+ """
24
+
25
+ CLOSED = auto()
26
+ """
27
+ The bracket stops at its limit. Default value.
28
+
29
+ Examples
30
+ --------
31
+ >>> import numdaplot as ndp
32
+ >>> ages = ndp.Table.from_arrays({"age": ndp.Array.from_list([4, 30])})
33
+ >>> brackets = ndp.Brackets(limits=[0, 18, 65], last=ndp.BracketEnd.CLOSED)
34
+ >>> ages.convert(ndp.Conversion(column="age", dtype=ndp.Type.CATEGORY, format=brackets)).column("age").to_list()
35
+ ['0 to 17', '18 to 64']
36
+ """
37
+
38
+ OPEN = auto()
39
+ """
40
+ The bracket holds every value beyond the limit: below the first one, or above the last one.
41
+
42
+ Examples
43
+ --------
44
+ >>> import numdaplot as ndp
45
+ >>> temperatures = ndp.Table.from_arrays({"celsius": ndp.Array.from_list([-3.5, 12.0])})
46
+ >>> brackets = ndp.Brackets(limits=[0, 15], first=ndp.BracketEnd.OPEN)
47
+ >>> conversion = ndp.Conversion(column="celsius", dtype=ndp.Type.CATEGORY, format=brackets)
48
+ >>> temperatures.convert(conversion).column("celsius").to_list()
49
+ ['under 0', '0 to under 15']
50
+ """
@@ -0,0 +1,346 @@
1
+ """
2
+ Names of brackets written from the values they hold.
3
+
4
+ .. versionadded:: 0.1.0
5
+ """
6
+
7
+ import math
8
+ from dataclasses import dataclass
9
+ from typing import cast
10
+
11
+ from numdaplot.errors.invalid_limits_error import InvalidLimitsError
12
+ from numdaplot.rules.bounds import Bounds
13
+ from numdaplot.tables.columns.bracket_end import BracketEnd
14
+ from numdaplot.tables.columns.brackets import Brackets
15
+
16
+ CLOSED_INTEGERS = "{low} to {high}"
17
+ INTEGERS_OR_MORE = "{low} or more"
18
+ INTEGERS_OR_LESS = "{high} or less"
19
+ LOW_DECIMALS = "{low} to under {high}"
20
+ HIGH_DECIMALS = "over {low} to {high}"
21
+ DECIMALS_OR_MORE = "{low} or more"
22
+ OVER_DECIMALS = "over {low}"
23
+ UNDER_DECIMALS = "under {high}"
24
+ DECIMALS_OR_LESS = "{high} or less"
25
+
26
+
27
+ @dataclass(frozen=True)
28
+ class Bracket:
29
+ """
30
+ One bracket: its low and its high limit, None on an open side.
31
+
32
+ .. versionadded:: 0.1.0
33
+
34
+ Parameters
35
+ ----------
36
+ low
37
+ The low limit, None for an open first bracket.
38
+ high
39
+ The high limit, None for an open last bracket.
40
+
41
+ Examples
42
+ --------
43
+ >>> from numdaplot.tables.columns.bracket_names import Bracket
44
+ >>> Bracket(0, 10).high
45
+ 10
46
+ """
47
+
48
+ low: int | float | None
49
+ high: int | float | None
50
+
51
+
52
+ def list_brackets(brackets: Brackets) -> list[Bracket]:
53
+ """
54
+ Return each bracket in order, open ones included.
55
+
56
+ .. versionadded:: 0.1.0
57
+
58
+ Parameters
59
+ ----------
60
+ brackets
61
+ The limits and the open ends.
62
+
63
+ Returns
64
+ -------
65
+ list[Bracket]
66
+ One bracket between two limits, an open one before the first limit or after the last one when asked.
67
+
68
+ Examples
69
+ --------
70
+ >>> import numdaplot as ndp
71
+ >>> from numdaplot.tables.columns.bracket_names import list_brackets
72
+ >>> list_brackets(ndp.Brackets(limits=[0, 10], last=ndp.BracketEnd.OPEN))
73
+ [Bracket(low=0, high=10), Bracket(low=10, high=None)]
74
+ """
75
+ bracket_list = list[Bracket]()
76
+ limits = brackets.limits
77
+ if brackets.first == BracketEnd.OPEN:
78
+ first_limit = limits[0]
79
+ open_first = Bracket(None, first_limit)
80
+ bracket_list.append(open_first)
81
+
82
+ for low, high in zip(limits, limits[1:], strict=False):
83
+ closed_bracket = Bracket(low, high)
84
+ bracket_list.append(closed_bracket)
85
+
86
+ if brackets.last == BracketEnd.OPEN:
87
+ last_limit = limits[-1]
88
+ open_last = Bracket(last_limit, None)
89
+ bracket_list.append(open_last)
90
+
91
+ return bracket_list
92
+
93
+
94
+ def write_bracket_names(brackets: Brackets, holds_integers: bool) -> list[str]:
95
+ """
96
+ Return the name of each bracket: the given labels, or the values each bracket holds.
97
+
98
+ .. versionadded:: 0.1.0
99
+
100
+ Parameters
101
+ ----------
102
+ brackets
103
+ The limits, the bounds, the open ends and the labels.
104
+ holds_integers
105
+ Whether the column holds integers, whose names give the first and the last integer of each bracket.
106
+
107
+ Returns
108
+ -------
109
+ list[str]
110
+ One name per bracket, in order.
111
+
112
+ Raises
113
+ ------
114
+ InvalidLimitsError
115
+ When a bracket between two limits holds no integer of a column of integers.
116
+
117
+ Examples
118
+ --------
119
+ >>> import numdaplot as ndp
120
+ >>> from numdaplot.tables.columns.bracket_names import write_bracket_names
121
+ >>> write_bracket_names(ndp.Brackets(limits=[0, 10, 20], last=ndp.BracketEnd.OPEN), True)
122
+ ['0 to 9', '10 to 19', '20 or more']
123
+ >>> write_bracket_names(ndp.Brackets(limits=[0, 10], bounds=ndp.Bounds.HIGH_ONLY), False)
124
+ ['over 0 to 10']
125
+ """
126
+ names = list[str]()
127
+ for bracket in list_brackets(brackets):
128
+ if holds_integers:
129
+ name = write_integer_name(bracket, brackets)
130
+ else:
131
+ name = write_decimal_name(bracket, brackets.bounds)
132
+
133
+ names.append(name)
134
+
135
+ if brackets.labels is not None:
136
+ return brackets.labels
137
+
138
+ return names
139
+
140
+
141
+ def write_integer_name(bracket: Bracket, brackets: Brackets) -> str:
142
+ """
143
+ Return the name of a bracket of integers: its first and its last integer.
144
+
145
+ .. versionadded:: 0.1.0
146
+
147
+ Parameters
148
+ ----------
149
+ bracket
150
+ The limits of the bracket.
151
+ brackets
152
+ The bounds, and the limits named by the error.
153
+
154
+ Returns
155
+ -------
156
+ str
157
+ ``0 to 9``, ``5`` for a single integer, ``80 or more`` or ``-1 or less`` for an open bracket.
158
+
159
+ Raises
160
+ ------
161
+ InvalidLimitsError
162
+ When the bracket holds no integer.
163
+
164
+ Examples
165
+ --------
166
+ >>> import numdaplot as ndp
167
+ >>> from numdaplot.tables.columns.bracket_names import Bracket, write_integer_name
168
+ >>> write_integer_name(Bracket(0.5, 10), ndp.Brackets(limits=[0.5, 10]))
169
+ '1 to 9'
170
+ """
171
+ if bracket.low is None:
172
+ # A bracket open on its low side always has a high limit, as Brackets needs a limit or an open end on each side.
173
+ high_limit = cast(int | float, bracket.high)
174
+ last_held = find_last_integer(high_limit, brackets.bounds)
175
+ less_name = INTEGERS_OR_LESS.format(high=last_held)
176
+ return less_name
177
+
178
+ first_integer = find_first_integer(bracket.low, brackets.bounds)
179
+ if bracket.high is None:
180
+ more_name = INTEGERS_OR_MORE.format(low=first_integer)
181
+ return more_name
182
+
183
+ last_integer = find_last_integer(bracket.high, brackets.bounds)
184
+ if first_integer > last_integer:
185
+ empty_bracket = [bracket.low, bracket.high]
186
+ raise InvalidLimitsError(brackets.limits, empty_bracket)
187
+
188
+ if first_integer == last_integer:
189
+ single_name = str(first_integer)
190
+ return single_name
191
+
192
+ closed_name = CLOSED_INTEGERS.format(low=first_integer, high=last_integer)
193
+
194
+ return closed_name
195
+
196
+
197
+ def find_first_integer(low: int | float, bounds: Bounds) -> int:
198
+ """
199
+ Return the smallest integer of a bracket from its low limit.
200
+
201
+ .. versionadded:: 0.1.0
202
+
203
+ Parameters
204
+ ----------
205
+ low
206
+ The low limit.
207
+ bounds
208
+ ``LOW_ONLY`` when the bracket holds its low limit, ``HIGH_ONLY`` otherwise.
209
+
210
+ Returns
211
+ -------
212
+ int
213
+ The low limit rounded up, plus one when the bracket does not hold it and it is a whole number.
214
+
215
+ Examples
216
+ --------
217
+ >>> import numdaplot as ndp
218
+ >>> from numdaplot.tables.columns.bracket_names import find_first_integer
219
+ >>> find_first_integer(10, ndp.Bounds.LOW_ONLY), find_first_integer(10, ndp.Bounds.HIGH_ONLY)
220
+ (10, 11)
221
+ """
222
+ if bounds == Bounds.LOW_ONLY:
223
+ held_low = math.ceil(low)
224
+ return held_low
225
+
226
+ low_floor = math.floor(low)
227
+ first_integer = low_floor + 1
228
+
229
+ return first_integer
230
+
231
+
232
+ def find_last_integer(high: int | float, bounds: Bounds) -> int:
233
+ """
234
+ Return the largest integer of a bracket from its high limit.
235
+
236
+ .. versionadded:: 0.1.0
237
+
238
+ Parameters
239
+ ----------
240
+ high
241
+ The high limit.
242
+ bounds
243
+ ``HIGH_ONLY`` when the bracket holds its high limit, ``LOW_ONLY`` otherwise.
244
+
245
+ Returns
246
+ -------
247
+ int
248
+ The high limit rounded down, minus one when the bracket does not hold it and it is a whole number.
249
+
250
+ Examples
251
+ --------
252
+ >>> import numdaplot as ndp
253
+ >>> from numdaplot.tables.columns.bracket_names import find_last_integer
254
+ >>> find_last_integer(10, ndp.Bounds.LOW_ONLY), find_last_integer(10, ndp.Bounds.HIGH_ONLY)
255
+ (9, 10)
256
+ """
257
+ if bounds == Bounds.HIGH_ONLY:
258
+ held_high = math.floor(high)
259
+ return held_high
260
+
261
+ high_ceiling = math.ceil(high)
262
+ last_integer = high_ceiling - 1
263
+
264
+ return last_integer
265
+
266
+
267
+ def write_decimal_name(bracket: Bracket, bounds: Bounds) -> str:
268
+ """
269
+ Return the name of a bracket of decimals, telling which limit it holds.
270
+
271
+ .. versionadded:: 0.1.0
272
+
273
+ Parameters
274
+ ----------
275
+ bracket
276
+ The limits of the bracket.
277
+ bounds
278
+ ``LOW_ONLY`` or ``HIGH_ONLY``.
279
+
280
+ Returns
281
+ -------
282
+ str
283
+ ``0 to under 10`` or ``over 0 to 10``, and for an open bracket ``80 or more``, ``over 80``, ``under 0`` or
284
+ ``0 or less``.
285
+
286
+ Examples
287
+ --------
288
+ >>> import numdaplot as ndp
289
+ >>> from numdaplot.tables.columns.bracket_names import Bracket, write_decimal_name
290
+ >>> write_decimal_name(Bracket(0.5, None), ndp.Bounds.HIGH_ONLY)
291
+ 'over 0.5'
292
+ """
293
+ low_text = write_limit(bracket.low)
294
+ high_text = write_limit(bracket.high)
295
+ holds_low = bounds == Bounds.LOW_ONLY
296
+ if bracket.low is None:
297
+ under_template = UNDER_DECIMALS if holds_low else DECIMALS_OR_LESS
298
+ under_name = under_template.format(high=high_text)
299
+ return under_name
300
+
301
+ if bracket.high is None:
302
+ over_template = DECIMALS_OR_MORE if holds_low else OVER_DECIMALS
303
+ over_name = over_template.format(low=low_text)
304
+ return over_name
305
+
306
+ closed_template = LOW_DECIMALS if holds_low else HIGH_DECIMALS
307
+ closed_name = closed_template.format(low=low_text, high=high_text)
308
+
309
+ return closed_name
310
+
311
+
312
+ def write_limit(limit: int | float | None) -> str:
313
+ """
314
+ Return a limit with the fewest digits that give it back, a whole number without decimals.
315
+
316
+ .. versionadded:: 0.1.0
317
+
318
+ Parameters
319
+ ----------
320
+ limit
321
+ A limit, or None.
322
+
323
+ Returns
324
+ -------
325
+ str
326
+ ``10`` for ``10`` or ``10.0``, ``0.1`` for ``0.1``, an empty text for None.
327
+
328
+ Examples
329
+ --------
330
+ >>> from numdaplot.tables.columns.bracket_names import write_limit
331
+ >>> write_limit(10.0), write_limit(0.1), write_limit(-3)
332
+ ('10', '0.1', '-3')
333
+ """
334
+ if limit is None:
335
+ return ""
336
+
337
+ decimal_limit = float(limit)
338
+ is_whole = decimal_limit.is_integer()
339
+ if is_whole:
340
+ whole_limit = int(limit)
341
+ whole_text = str(whole_limit)
342
+ return whole_text
343
+
344
+ shortest_text = repr(limit)
345
+
346
+ return shortest_text
@@ -0,0 +1,179 @@
1
+ """
2
+ Conversion of a number column to the categories of its brackets.
3
+
4
+ .. versionadded:: 0.1.0
5
+ """
6
+
7
+ from typing import Any, cast
8
+
9
+ import numpy
10
+ import pandas
11
+ from numpy.typing import NDArray
12
+
13
+ from numdaplot.arrays.mapping.unmatched import Unmatched
14
+ from numdaplot.data_types.pandas_mapping import to_pandas_dtype
15
+ from numdaplot.data_types.type import Type
16
+ from numdaplot.errors.unmatched_value_error import BRACKETS_NAME, UnmatchedValueError
17
+ from numdaplot.rules.bounds import Bounds
18
+ from numdaplot.tables.columns.bracket_end import BracketEnd
19
+ from numdaplot.tables.columns.bracket_names import write_bracket_names
20
+ from numdaplot.tables.columns.brackets import Brackets
21
+ from numdaplot.tables.frames.column import Column
22
+ from numdaplot.tables.frames.column_values import find_column_missing, find_column_type
23
+ from numdaplot.tables.frames.frame_normalization import convert_to_type
24
+
25
+ INTEGER_TYPES = frozenset(
26
+ {Type.INT8, Type.INT16, Type.INT32, Type.INT64, Type.UINT8, Type.UINT16, Type.UINT32, Type.UINT64}
27
+ )
28
+ NO_CATEGORY = -1
29
+ DECIMAL_DTYPE = numpy.float64
30
+ LOW_SIDE = "right"
31
+ HIGH_SIDE = "left"
32
+
33
+
34
+ def cut_column(column: Column, brackets: Brackets) -> Column:
35
+ """
36
+ Return a number column as the categories of its brackets, in the order of the brackets.
37
+
38
+ .. versionadded:: 0.1.0
39
+
40
+ Parameters
41
+ ----------
42
+ column
43
+ A Table column of numbers.
44
+ brackets
45
+ The limits, the bounds, the open ends, the labels and what happens to a value in no bracket.
46
+
47
+ Returns
48
+ -------
49
+ Column
50
+ A ``CATEGORY`` column whose categories are the names of the brackets, missing values staying missing.
51
+
52
+ Raises
53
+ ------
54
+ InvalidLimitsError
55
+ When a bracket between two limits holds no integer of a column of integers.
56
+ UnmatchedValueError
57
+ At the first value in no bracket, when ``others`` is ``Unmatched.ERROR``.
58
+
59
+ Examples
60
+ --------
61
+ >>> import pandas
62
+ >>> import numdaplot as ndp
63
+ >>> from numdaplot.tables.columns.bracketed_column import cut_column
64
+ >>> ages = pandas.Series([4, None, 30], dtype="Int64")
65
+ >>> cut_column(ages, ndp.Brackets(limits=[0, 18, 65])).tolist()
66
+ ['0 to 17', <NA>, '18 to 64']
67
+ """
68
+ column_type = find_column_type(column)
69
+ holds_integers = column_type in INTEGER_TYPES
70
+ names = write_bracket_names(brackets, holds_integers)
71
+ missing = find_column_missing(column)
72
+ numbers = column.to_numpy(dtype=DECIMAL_DTYPE, na_value=numpy.nan)
73
+ positions = find_bracket_positions(numbers, brackets)
74
+ has_no_bracket = positions == NO_CATEGORY
75
+ unmatched = has_no_bracket & ~missing
76
+ require_matched_values(column, unmatched, brackets.others)
77
+ text_dtype = to_pandas_dtype(Type.TEXT)
78
+ categories = pandas.Index(names, dtype=text_dtype)
79
+ # Some versions of the pandas stubs only accept a sequence of integers as codes.
80
+ categorical_class = cast(Any, pandas.Categorical)
81
+ raw_categorical = categorical_class.from_codes(positions, categories=categories)
82
+ categorical = cast(pandas.Categorical, raw_categorical)
83
+ category_column = pandas.Series(categorical, index=column.index)
84
+ stored_column = convert_to_type(category_column, Type.CATEGORY)
85
+
86
+ return stored_column
87
+
88
+
89
+ def find_bracket_positions(numbers: NDArray[numpy.float64], brackets: Brackets) -> NDArray[numpy.intp]:
90
+ """
91
+ Return the position of the bracket of each number, -1 for a missing number or a number in no bracket.
92
+
93
+ .. versionadded:: 0.1.0
94
+
95
+ Parameters
96
+ ----------
97
+ numbers
98
+ The numbers, NaN where missing.
99
+ brackets
100
+ The limits, the bounds and the open ends.
101
+
102
+ Returns
103
+ -------
104
+ NDArray[numpy.intp]
105
+ The position of each bracket, counted from the first one, open or not.
106
+
107
+ Examples
108
+ --------
109
+ >>> import numpy
110
+ >>> import numdaplot as ndp
111
+ >>> from numdaplot.tables.columns.bracketed_column import find_bracket_positions
112
+ >>> brackets = ndp.Brackets(limits=[0, 10, 20], first=ndp.BracketEnd.OPEN)
113
+ >>> find_bracket_positions(numpy.array([-5.0, 0.0, 10.0, 25.0, numpy.nan]), brackets)
114
+ array([ 0, 1, 2, -1, -1])
115
+ """
116
+ limits = numpy.array(brackets.limits, dtype=DECIMAL_DTYPE)
117
+ side = LOW_SIDE if brackets.bounds == Bounds.LOW_ONLY else HIGH_SIDE
118
+ limit_counts = numpy.searchsorted(limits, numbers, side=side)
119
+ first_offset = 1 if brackets.first == BracketEnd.OPEN else 0
120
+ positions = limit_counts - 1 + first_offset
121
+ is_matched = ~numpy.isnan(numbers)
122
+ if brackets.first == BracketEnd.CLOSED:
123
+ is_above_first = limit_counts > 0
124
+ is_matched = is_matched & is_above_first
125
+
126
+ if brackets.last == BracketEnd.CLOSED:
127
+ limit_count = limits.size
128
+ is_below_last = limit_counts < limit_count
129
+ is_matched = is_matched & is_below_last
130
+
131
+ matched_positions = numpy.where(is_matched, positions, NO_CATEGORY)
132
+
133
+ return matched_positions
134
+
135
+
136
+ def require_matched_values(column: Column, unmatched: NDArray[numpy.bool_], others: Unmatched) -> None:
137
+ """
138
+ Check that every present number is in a bracket, unless the numbers in no bracket become missing.
139
+
140
+ .. versionadded:: 0.1.0
141
+
142
+ Parameters
143
+ ----------
144
+ column
145
+ The Table column of numbers.
146
+ unmatched
147
+ True at each present number in no bracket.
148
+ others
149
+ ``Unmatched.ERROR`` to refuse such a number, ``Unmatched.MISSING`` to make it missing.
150
+
151
+ Raises
152
+ ------
153
+ UnmatchedValueError
154
+ At the first number in no bracket, with ``Unmatched.ERROR``.
155
+
156
+ Examples
157
+ --------
158
+ >>> import numpy
159
+ >>> import pandas
160
+ >>> import numdaplot as ndp
161
+ >>> from numdaplot.tables.columns.bracketed_column import require_matched_values
162
+ >>> try:
163
+ ... require_matched_values(pandas.Series([5, 105]), numpy.array([False, True]), ndp.Unmatched.ERROR)
164
+ ... except ndp.UnmatchedValueError as error:
165
+ ... print(error.value)
166
+ 105
167
+ """
168
+ if others == Unmatched.MISSING:
169
+ return
170
+
171
+ has_unmatched = bool(unmatched.any())
172
+ if not has_unmatched:
173
+ return
174
+
175
+ unmatched_positions = numpy.flatnonzero(unmatched)
176
+ first_position = int(unmatched_positions[0])
177
+ python_values = column.tolist()
178
+ first_value = python_values[first_position]
179
+ raise UnmatchedValueError(first_value, BRACKETS_NAME)