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,113 @@
1
+ """
2
+ Rows and columns of a Table chosen by a Region.
3
+
4
+ .. versionadded:: 0.1.0
5
+ """
6
+
7
+ from typing import Any
8
+
9
+ import numpy
10
+ import pandas
11
+ from numpy.typing import NDArray
12
+
13
+ from numdaplot.arrays.selection.region_index import find_positions
14
+ from numdaplot.positions.index import Index
15
+ from numdaplot.positions.range import Range
16
+ from numdaplot.positions.region import Region
17
+ from numdaplot.tables.columns.column_names import require_known_columns, require_unique_names
18
+
19
+ POSITION_DTYPE = numpy.int64
20
+
21
+
22
+ def take_region(frame: pandas.DataFrame, region: Region) -> pandas.DataFrame:
23
+ """
24
+ Return the rows and the columns of a Table chosen by a Region.
25
+
26
+ .. versionadded:: 0.1.0
27
+
28
+ Parameters
29
+ ----------
30
+ frame
31
+ The columns of a Table.
32
+ region
33
+ The rows and the columns to take, every one of a dimension when omitted.
34
+
35
+ Returns
36
+ -------
37
+ pandas.DataFrame
38
+ The chosen part, rows numbered from 0, columns in the order of the region.
39
+
40
+ Raises
41
+ ------
42
+ InvalidPositionError
43
+ When a position is not a whole number inside its dimension.
44
+ ColumnNotFoundError
45
+ When a column name matches no column.
46
+ DuplicateColumnError
47
+ When a column name appears twice in the region.
48
+
49
+ Examples
50
+ --------
51
+ >>> import pandas
52
+ >>> import numdaplot as ndp
53
+ >>> from numdaplot.tables.frames.region_positions import take_region
54
+ >>> frame = pandas.DataFrame({"city": ["Paris", "Lyon"], "price": [1.5, 8.0]})
55
+ >>> take_region(frame, ndp.Region(rows=ndp.Index(-1), columns=["price"]))
56
+ price
57
+ 0 8.0
58
+ """
59
+ row_count = len(frame)
60
+ row_positions = find_positions(region.rows, row_count)
61
+ column_names = [str(column_name) for column_name in frame.columns]
62
+ column_positions = find_column_positions(region.columns, column_names)
63
+ region_frame = frame.iloc[row_positions, column_positions]
64
+ numbered_frame = region_frame.reset_index(drop=True)
65
+
66
+ return numbered_frame
67
+
68
+
69
+ def find_column_positions(columns: Index | Range | list[str] | None, column_names: list[str]) -> NDArray[Any]:
70
+ """
71
+ Return the positions of the columns chosen by a Region.
72
+
73
+ .. versionadded:: 0.1.0
74
+
75
+ Parameters
76
+ ----------
77
+ columns
78
+ One position, a sequence of positions, a list of names, or ``None`` for every column.
79
+ column_names
80
+ The names of the columns of the Table.
81
+
82
+ Returns
83
+ -------
84
+ NDArray
85
+ The chosen positions, in the order of the region.
86
+
87
+ Raises
88
+ ------
89
+ InvalidPositionError
90
+ When a position is not a whole number inside the columns.
91
+ ColumnNotFoundError
92
+ When a name matches no column.
93
+ DuplicateColumnError
94
+ When a name appears twice.
95
+
96
+ Examples
97
+ --------
98
+ >>> from numdaplot.tables.frames.region_positions import find_column_positions
99
+ >>> find_column_positions(["price", "city"], ["city", "price"])
100
+ array([1, 0])
101
+ """
102
+ if not isinstance(columns, list):
103
+ column_count = len(column_names)
104
+ positions = find_positions(columns, column_count)
105
+ return positions
106
+
107
+ require_unique_names(columns)
108
+ require_known_columns(columns, column_names)
109
+ positions_by_name = {column_name: position for position, column_name in enumerate(column_names)}
110
+ named_positions = [positions_by_name[column_name] for column_name in columns]
111
+ positions = numpy.array(named_positions, dtype=POSITION_DTYPE)
112
+
113
+ return positions
@@ -0,0 +1,222 @@
1
+ """
2
+ Text of a Table, with the type of each column under its name.
3
+
4
+ .. versionadded:: 0.1.0
5
+ """
6
+
7
+ from shutil import get_terminal_size
8
+
9
+ import pandas
10
+
11
+ from numdaplot.tables.frames.column_values import find_column_type
12
+ from numdaplot.tables.frames.time_columns import is_time_column, write_time_texts_column
13
+ from numdaplot.tables.frames.time_zones import name_column_type
14
+ from numdaplot.tables.preview.shown_columns import ShownColumns
15
+
16
+ MAX_COLUMNS_OPTION = "display.max_columns"
17
+ WIDTH_OPTION = "display.width"
18
+ # In pandas, no limit shows every column, and a limit of 0 only shows those fitting in the width.
19
+ NO_ROWS_NOTE = "(0 rows)"
20
+ NO_COLUMNS_NOTE = "(no columns, {rows_text})"
21
+ ONE_ROW_TEXT = "1 row"
22
+ ROWS_TEXT = "{row_count} rows"
23
+ BLANK_CELL = ""
24
+ BLANK_ROW_START = "0"
25
+ LINE_BREAK = "\n"
26
+ SHOW_DIMENSIONS_OPTION = "display.show_dimensions"
27
+ COLUMN_LIMITS = {
28
+ ShownColumns.ALL: None,
29
+ ShownColumns.COMPACT: 0,
30
+ }
31
+
32
+
33
+ def build_typed_frame(frame: pandas.DataFrame) -> pandas.DataFrame:
34
+ """
35
+ Return a copy of the columns of a Table whose header shows the name, then the type, of each column.
36
+
37
+ .. versionadded:: 0.1.0
38
+
39
+ Parameters
40
+ ----------
41
+ frame
42
+ The columns of a Table.
43
+
44
+ Returns
45
+ -------
46
+ pandas.DataFrame
47
+ A copy with a two-level header: the column names, then the names of their ``ndp.Type``, followed by
48
+ the time zone of a datetime column that has one.
49
+
50
+ Examples
51
+ --------
52
+ >>> import pandas
53
+ >>> from numdaplot.tables.frames.table_text import build_typed_frame
54
+ >>> build_typed_frame(pandas.DataFrame({"price": [1.5]})).columns.tolist()
55
+ [('price', 'FLOAT64')]
56
+ """
57
+ column_names = list(frame.columns)
58
+ type_names = list[str]()
59
+
60
+ for column_name in column_names:
61
+ column = frame[column_name]
62
+ column_type = find_column_type(column)
63
+ type_name = name_column_type(column, column_type)
64
+ type_names.append(type_name)
65
+
66
+ header = pandas.MultiIndex.from_arrays([column_names, type_names])
67
+ typed_frame = frame.copy()
68
+ for column_name in column_names:
69
+ column = frame[column_name]
70
+ if is_time_column(column):
71
+ typed_frame[column_name] = write_time_texts_column(column)
72
+
73
+ typed_frame.columns = header
74
+
75
+ return typed_frame
76
+
77
+
78
+ def format_table(frame: pandas.DataFrame, shown_columns: ShownColumns = ShownColumns.ALL) -> str:
79
+ """
80
+ Return the text pandas shows for the columns of a Table, with the type of each column under its name.
81
+
82
+ A long Table only shows its first and last rows, following the pandas display settings. The columns follow the
83
+ width of the terminal, whatever the pandas display settings.
84
+
85
+ .. versionadded:: 0.1.0
86
+
87
+ Parameters
88
+ ----------
89
+ frame
90
+ The columns of a Table.
91
+ shown_columns
92
+ ``ShownColumns.ALL`` by default for every column, going on after a line break when they do not fit, or
93
+ ``ShownColumns.COMPACT`` to replace those that do not fit by ``...``.
94
+
95
+ Returns
96
+ -------
97
+ str
98
+ The text of the Table, with row numbers on the left.
99
+
100
+ Examples
101
+ --------
102
+ >>> import pandas
103
+ >>> from numdaplot.tables.frames.table_text import format_table
104
+ >>> print(format_table(pandas.DataFrame({"price": [1.5, 8.0]})))
105
+ price
106
+ FLOAT64
107
+ 0 1.5
108
+ 1 8.0
109
+ """
110
+ empty_table_text = format_empty_table(frame, shown_columns)
111
+ if empty_table_text is not None:
112
+ return empty_table_text
113
+
114
+ typed_frame = build_typed_frame(frame)
115
+ column_limit = COLUMN_LIMITS[shown_columns]
116
+ terminal_size = get_terminal_size()
117
+ with pandas.option_context(MAX_COLUMNS_OPTION, column_limit, WIDTH_OPTION, terminal_size.columns):
118
+ table_text = repr(typed_frame)
119
+
120
+ return table_text
121
+
122
+
123
+ def write_empty_table_note(frame: pandas.DataFrame) -> str | None:
124
+ """
125
+ Return the note replacing the rows of a Table without rows or without columns.
126
+
127
+ .. versionadded:: 0.1.0
128
+
129
+ Parameters
130
+ ----------
131
+ frame
132
+ The columns of a Table.
133
+
134
+ Returns
135
+ -------
136
+ str or None
137
+ ``(0 rows)``, ``(no columns, 2 rows)``, or None for a Table with values.
138
+
139
+ Examples
140
+ --------
141
+ >>> import pandas
142
+ >>> from numdaplot.tables.frames.table_text import write_empty_table_note
143
+ >>> write_empty_table_note(pandas.DataFrame({"price": [1.5]})) is None
144
+ True
145
+ >>> write_empty_table_note(pandas.DataFrame(index=[0, 1]))
146
+ '(no columns, 2 rows)'
147
+ >>> write_empty_table_note(pandas.DataFrame(index=[0]))
148
+ '(no columns, 1 row)'
149
+ """
150
+ row_count = len(frame.index)
151
+ column_count = len(frame.columns)
152
+ if column_count == 0:
153
+ rows_text = ONE_ROW_TEXT if row_count == 1 else ROWS_TEXT.format(row_count=row_count)
154
+ no_columns_note = NO_COLUMNS_NOTE.format(rows_text=rows_text)
155
+ return no_columns_note
156
+
157
+ if row_count == 0:
158
+ return NO_ROWS_NOTE
159
+
160
+ return None
161
+
162
+
163
+ def format_empty_table(frame: pandas.DataFrame, shown_columns: ShownColumns) -> str | None:
164
+ """
165
+ Return the text of a Table without rows or without columns: its header if any, then a note.
166
+
167
+ pandas writes such a Table with its own words, so the header comes from a Table of one blank row.
168
+
169
+ .. versionadded:: 0.1.0
170
+
171
+ Parameters
172
+ ----------
173
+ frame
174
+ The columns of a Table.
175
+ shown_columns
176
+ ``ShownColumns.ALL`` for every column, or ``ShownColumns.COMPACT`` to replace those that do not fit by ``...``.
177
+
178
+ Returns
179
+ -------
180
+ str or None
181
+ The text, or None for a Table with values.
182
+
183
+ Examples
184
+ --------
185
+ >>> import pandas
186
+ >>> from numdaplot.tables.frames.table_text import format_empty_table
187
+ >>> from numdaplot.tables.preview.shown_columns import ShownColumns
188
+ >>> prices = pandas.DataFrame({"price": pandas.Series(dtype="float64")})
189
+ >>> print(format_empty_table(prices, ShownColumns.ALL))
190
+ price
191
+ FLOAT64
192
+ (0 rows)
193
+ """
194
+ note = write_empty_table_note(frame)
195
+ if note is None:
196
+ return None
197
+
198
+ column_count = len(frame.columns)
199
+ if column_count == 0:
200
+ return note
201
+
202
+ typed_frame = build_typed_frame(frame)
203
+ blank_row = [[BLANK_CELL] * column_count]
204
+ blank_frame = pandas.DataFrame(blank_row, columns=typed_frame.columns)
205
+ column_limit = COLUMN_LIMITS[shown_columns]
206
+ terminal_size = get_terminal_size()
207
+ with pandas.option_context(
208
+ MAX_COLUMNS_OPTION,
209
+ column_limit,
210
+ WIDTH_OPTION,
211
+ terminal_size.columns,
212
+ SHOW_DIMENSIONS_OPTION,
213
+ False,
214
+ ):
215
+ blank_text = repr(blank_frame)
216
+
217
+ lines = blank_text.splitlines()
218
+ header_lines = [line for line in lines if not line.startswith(BLANK_ROW_START)]
219
+ empty_table_lines = [*header_lines, note]
220
+ empty_table_text = LINE_BREAK.join(empty_table_lines)
221
+
222
+ return empty_table_text
@@ -0,0 +1,345 @@
1
+ """
2
+ Table columns of times of day, and the durations a Table reads from outside numdaplot.
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.conversion.time_text import format_times
14
+ from numdaplot.data_types.time_of_day import TIME_DTYPE, read_time_objects, store_time_objects
15
+ from numdaplot.tables.frames.column import Column
16
+ from numdaplot.tables.frames.time_range_errors import TimeRangeErrors
17
+
18
+ DURATION_KIND = "m"
19
+ NANOSECOND_DURATION_DTYPE = numpy.dtype("timedelta64[ns]")
20
+ PYTHON_OBJECT_DTYPE = numpy.dtype(object)
21
+ TEXT_PANDAS_DTYPE = "string"
22
+ TABLE_CREATION_OPERATION = "Table creation"
23
+
24
+
25
+ def is_time_column(column: Column) -> bool:
26
+ """
27
+ Return whether a Table column stores times of day.
28
+
29
+ .. versionadded:: 0.1.0
30
+
31
+ Parameters
32
+ ----------
33
+ column
34
+ A Table column.
35
+
36
+ Returns
37
+ -------
38
+ bool
39
+ True for a column in ``timedelta64[us]``.
40
+
41
+ Examples
42
+ --------
43
+ >>> import pandas
44
+ >>> from numdaplot.tables.frames.time_columns import is_time_column
45
+ >>> import numpy
46
+ >>> is_time_column(pandas.Series(numpy.array([1], dtype="timedelta64[us]"))), is_time_column(pandas.Series([1]))
47
+ (True, False)
48
+ """
49
+ holds_times = column.dtype == TIME_DTYPE
50
+
51
+ return holds_times
52
+
53
+
54
+ def read_time_objects_column(column: Column) -> Column:
55
+ """
56
+ Return a column of times of day as Python ``datetime.time`` objects, None where missing.
57
+
58
+ .. versionadded:: 0.1.0
59
+
60
+ Parameters
61
+ ----------
62
+ column
63
+ A Table column of times of day.
64
+
65
+ Returns
66
+ -------
67
+ Column
68
+ An object column with the same index.
69
+
70
+ Examples
71
+ --------
72
+ >>> import pandas
73
+ >>> from numdaplot.tables.frames.time_columns import read_time_objects_column
74
+ >>> import numpy
75
+ >>> minutes = pandas.Series(numpy.array([60000000], dtype="timedelta64[us]"))
76
+ >>> read_time_objects_column(minutes).tolist()
77
+ [datetime.time(0, 1)]
78
+ """
79
+ stored_times = column.to_numpy(dtype=TIME_DTYPE)
80
+ time_objects = read_time_objects(stored_times)
81
+ object_column = pandas.Series(time_objects, index=column.index, name=column.name, dtype=PYTHON_OBJECT_DTYPE)
82
+
83
+ return object_column
84
+
85
+
86
+ def store_time_column(column: Column) -> Column:
87
+ """
88
+ Return a column of Python times of day stored as the time since midnight.
89
+
90
+ .. versionadded:: 0.1.0
91
+
92
+ Parameters
93
+ ----------
94
+ column
95
+ An object column of ``datetime.time`` and missing values.
96
+
97
+ Returns
98
+ -------
99
+ Column
100
+ A column in ``timedelta64[us]`` with the same index, NaT where missing.
101
+
102
+ Examples
103
+ --------
104
+ >>> from datetime import time
105
+ >>> import pandas
106
+ >>> from numdaplot.tables.frames.time_columns import store_time_column
107
+ >>> store_time_column(pandas.Series([time(0, 1), None], dtype=object)).tolist()
108
+ [Timedelta('0 days 00:01:00'), NaT]
109
+ """
110
+ object_values = read_object_values(column)
111
+ stored_times = store_time_objects(object_values)
112
+ time_column = pandas.Series(stored_times, index=column.index, name=column.name)
113
+
114
+ return time_column
115
+
116
+
117
+ def read_object_values(column: Column) -> NDArray[Any]:
118
+ """
119
+ Return the values of a column as Python objects, None where missing.
120
+
121
+ .. versionadded:: 0.1.0
122
+
123
+ Parameters
124
+ ----------
125
+ column
126
+ A column of any dtype.
127
+
128
+ Returns
129
+ -------
130
+ NDArray
131
+ An object array, None for every missing marker such as NaN or ``pd.NA``.
132
+
133
+ Examples
134
+ --------
135
+ >>> import pandas
136
+ >>> from numdaplot.tables.frames.time_columns import read_object_values
137
+ >>> read_object_values(pandas.Series(["a", float("nan")], dtype=object))
138
+ array(['a', None], dtype=object)
139
+ """
140
+ missing = column.isna()
141
+ missing_flags = missing.to_numpy(dtype=bool)
142
+ # Some versions of the numpy stubs refuse None as a value of an object array.
143
+ object_values = cast(Any, column.to_numpy(dtype=PYTHON_OBJECT_DTYPE, copy=True))
144
+ object_values[missing_flags] = None
145
+
146
+ return object_values
147
+
148
+
149
+ def convert_outside_durations(frame: pandas.DataFrame) -> pandas.DataFrame:
150
+ """
151
+ Return a DataFrame read from outside numdaplot whose durations, of any unit, are stored in nanoseconds.
152
+
153
+ Microseconds store the times of day, so an outside duration in microseconds must not keep them.
154
+
155
+ .. versionadded:: 0.1.0
156
+
157
+ Parameters
158
+ ----------
159
+ frame
160
+ A DataFrame read from a file or given by the user. It is not changed.
161
+
162
+ Returns
163
+ -------
164
+ pandas.DataFrame
165
+ The DataFrame, a copy with its duration columns in ``timedelta64[ns]`` when it has some.
166
+
167
+ Raises
168
+ ------
169
+ TimeOverflowError
170
+ When a duration is beyond about 292 years, which nanoseconds cannot hold.
171
+
172
+ Examples
173
+ --------
174
+ >>> import pandas
175
+ >>> from numdaplot.tables.frames.time_columns import convert_outside_durations
176
+ >>> import numpy
177
+ >>> frame = pandas.DataFrame({"wait": numpy.array([5], dtype="timedelta64[us]")})
178
+ >>> convert_outside_durations(frame).dtypes.tolist()
179
+ [dtype('<m8[ns]')]
180
+ """
181
+ duration_names = [name for name in frame.columns if frame[name].dtype.kind == DURATION_KIND]
182
+ if duration_names == []:
183
+ return frame
184
+
185
+ converted_frame = frame.copy(deep=False)
186
+ for column_name in duration_names:
187
+ column = frame[column_name]
188
+ duration_values = column.to_numpy()
189
+ nanosecond_values = convert_to_nanoseconds(duration_values, str(column_name))
190
+ nanosecond_column = pandas.Series(nanosecond_values, index=column.index, name=column.name)
191
+ converted_frame[column_name] = nanosecond_column
192
+
193
+ return converted_frame
194
+
195
+
196
+ def convert_to_nanoseconds(durations: NDArray[Any], column_name: str) -> NDArray[Any]:
197
+ """
198
+ Return durations of any unit in nanoseconds, refusing those that nanoseconds cannot hold.
199
+
200
+ .. versionadded:: 0.1.0
201
+
202
+ Parameters
203
+ ----------
204
+ durations
205
+ Durations in ``timedelta64`` of any unit.
206
+ column_name
207
+ The name of the column holding them, named by the error.
208
+
209
+ Returns
210
+ -------
211
+ NDArray
212
+ The durations in ``timedelta64[ns]``.
213
+
214
+ Raises
215
+ ------
216
+ TimeOverflowError
217
+ When a duration is beyond about 292 years.
218
+
219
+ Examples
220
+ --------
221
+ >>> import numpy
222
+ >>> from numdaplot.tables.frames.time_columns import convert_to_nanoseconds
223
+ >>> convert_to_nanoseconds(numpy.array([2], dtype="timedelta64[s]"), "wait")
224
+ array([2000000000], dtype='timedelta64[ns]')
225
+ """
226
+ with TimeRangeErrors(TABLE_CREATION_OPERATION, column_name):
227
+ try:
228
+ nanosecond_values = durations.astype(NANOSECOND_DURATION_DTYPE)
229
+ except OverflowError as error:
230
+ raise pandas.errors.OutOfBoundsTimedelta from error
231
+
232
+ # Some versions of numpy wrap a duration beyond the range of nanoseconds instead of raising.
233
+ original_values = nanosecond_values.astype(durations.dtype)
234
+ is_kept = (original_values == durations) | numpy.isnat(durations)
235
+ is_exact = bool(is_kept.all())
236
+ if not is_exact:
237
+ raise pandas.errors.OutOfBoundsTimedelta
238
+
239
+ return nanosecond_values
240
+
241
+
242
+ def read_time_objects_frame(frame: pandas.DataFrame) -> pandas.DataFrame:
243
+ """
244
+ Return a DataFrame whose columns of times of day hold Python ``datetime.time`` objects.
245
+
246
+ .. versionadded:: 0.1.0
247
+
248
+ Parameters
249
+ ----------
250
+ frame
251
+ The columns of a Table. It is not changed.
252
+
253
+ Returns
254
+ -------
255
+ pandas.DataFrame
256
+ A deep copy, each column of times of day as an object column.
257
+
258
+ Examples
259
+ --------
260
+ >>> import pandas
261
+ >>> from numdaplot.tables.frames.time_columns import read_time_objects_frame
262
+ >>> import numpy
263
+ >>> frame = pandas.DataFrame({"hour": numpy.array([60000000], dtype="timedelta64[us]")})
264
+ >>> read_time_objects_frame(frame)["hour"].tolist()
265
+ [datetime.time(0, 1)]
266
+ """
267
+ frame_copy = frame.copy(deep=True)
268
+ for column_name in frame.columns:
269
+ column = frame[column_name]
270
+ if is_time_column(column):
271
+ object_column = read_time_objects_column(column)
272
+ frame_copy[column_name] = object_column
273
+
274
+ return frame_copy
275
+
276
+
277
+ def write_time_texts_column(column: Column) -> Column:
278
+ """
279
+ Return a column of times of day as texts, such as ``15:35:00``, ``NaT`` where missing.
280
+
281
+ .. versionadded:: 0.1.0
282
+
283
+ Parameters
284
+ ----------
285
+ column
286
+ A Table column of times of day.
287
+
288
+ Returns
289
+ -------
290
+ Column
291
+ An object column of texts with the same index.
292
+
293
+ Examples
294
+ --------
295
+ >>> import pandas
296
+ >>> from numdaplot.tables.frames.time_columns import write_time_texts_column
297
+ >>> import numpy
298
+ >>> hours = pandas.Series(numpy.array([56100000000, "NaT"], dtype="timedelta64[us]"))
299
+ >>> write_time_texts_column(hours).tolist()
300
+ ['15:35:00', 'NaT']
301
+ """
302
+ stored_times = column.to_numpy(dtype=TIME_DTYPE)
303
+ time_texts = format_times(stored_times)
304
+ text_column = pandas.Series(time_texts, index=column.index, name=column.name, dtype=PYTHON_OBJECT_DTYPE)
305
+
306
+ return text_column
307
+
308
+
309
+ def write_time_texts_frame(frame: pandas.DataFrame) -> pandas.DataFrame:
310
+ """
311
+ Return a DataFrame whose columns of times of day are written as texts, missing where a time is missing.
312
+
313
+ .. versionadded:: 0.1.0
314
+
315
+ Parameters
316
+ ----------
317
+ frame
318
+ The columns of a Table. It is not changed.
319
+
320
+ Returns
321
+ -------
322
+ pandas.DataFrame
323
+ A copy, each column of times of day as texts such as ``15:35:00``.
324
+
325
+ Examples
326
+ --------
327
+ >>> import numpy
328
+ >>> import pandas
329
+ >>> from numdaplot.tables.frames.time_columns import write_time_texts_frame
330
+ >>> frame = pandas.DataFrame({"hour": numpy.array([56100000000, "NaT"], dtype="timedelta64[us]")})
331
+ >>> write_time_texts_frame(frame)["hour"].tolist()
332
+ ['15:35:00', <NA>]
333
+ """
334
+ text_frame = frame.copy()
335
+ for column_name in frame.columns:
336
+ column = frame[column_name]
337
+ if is_time_column(column):
338
+ time_texts = write_time_texts_column(column)
339
+ missing = column.isna()
340
+ # Some versions of the pandas stubs leave the types of mask partly unknown.
341
+ text_column = cast(Any, time_texts)
342
+ present_texts = cast(Column, text_column.mask(missing))
343
+ text_frame[column_name] = present_texts.astype(TEXT_PANDAS_DTYPE)
344
+
345
+ return text_frame