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,313 @@
1
+ """
2
+ Drawing of a HeatmapChart.
3
+
4
+ .. versionadded:: 0.1.0
5
+ """
6
+
7
+ # The matplotlib stubs leave the keyword arguments of most drawing methods untyped.
8
+ # pyright: reportUnknownMemberType=false
9
+
10
+ import warnings
11
+ from typing import cast
12
+
13
+ import matplotlib
14
+ import numpy
15
+ from matplotlib.axes import Axes
16
+ from matplotlib.image import AxesImage
17
+ from numpy.typing import NDArray
18
+
19
+ from numdaplot.arrays.operations.float_errors import INTERNAL_FILES
20
+ from numdaplot.errors.readability_warning import ReadabilityWarning
21
+ from numdaplot.plots.chart_layer import ChartLayer
22
+ from numdaplot.plots.charts.cell_values import CellValues
23
+ from numdaplot.plots.charts.heatmap_chart import HeatmapChart
24
+ from numdaplot.plots.data.chart_values import ChartValues, Series
25
+ from numdaplot.plots.drawing.cell_merging import average_cells, find_cell_limits, fit_cells_to_axes
26
+ from numdaplot.plots.drawing.color_bar import add_color_bar
27
+ from numdaplot.plots.drawing.color_scale_values import SCALE_NAMES, find_scale_limits
28
+ from numdaplot.plots.drawing.default_labels import COLUMN_LABEL, find_position_label
29
+ from numdaplot.plots.drawing.drawn_chart import DrawnChart
30
+ from numdaplot.plots.drawing.grid_axes import GridAxes
31
+ from numdaplot.plots.drawing.plot_theme import GRID_COLOR
32
+ from numdaplot.plots.drawing.position_axis import TRIMMED_ZEROS, place_categories, set_fixed_labels
33
+ from numdaplot.plots.drawing.text_contrast import choose_text_color
34
+
35
+ CELL_DECIMALS = 2
36
+ CELL_ASPECT = "auto"
37
+ CELL_INTERPOLATION = "nearest"
38
+ CENTERED = "center"
39
+ MERGED_CELLS_MESSAGE = (
40
+ "A HeatmapChart with {row_count} rows and {column_count} columns does not fit in the image, so each band shows the "
41
+ "mean of its cells. Give a larger ndp.Size, or group the values with Table.aggregate first."
42
+ )
43
+ UNWRITTEN_VALUES_MESSAGE = " The values of the cells are not written."
44
+
45
+
46
+ def draw_heatmap_chart(axes: Axes, layer: ChartLayer) -> DrawnChart:
47
+ """
48
+ Draw each value as a cell colored along a color scale, the columns side by side and the first row on top.
49
+
50
+ When the axes have too few pixels for the cells, each band shows the mean of its cells, missing values left out,
51
+ the color scale follows these means, and the values of the cells are not written.
52
+
53
+ .. versionadded:: 0.1.0
54
+
55
+ Parameters
56
+ ----------
57
+ axes
58
+ The matplotlib axes drawn on.
59
+ layer
60
+ A HeatmapChart, its row labels and its columns.
61
+
62
+ Returns
63
+ -------
64
+ DrawnChart
65
+ The ``labels`` column as default label of the vertical axis, and no grid lines.
66
+
67
+ Warns
68
+ -----
69
+ ReadabilityWarning
70
+ When the cells are merged into bands.
71
+
72
+ Examples
73
+ --------
74
+ >>> import numdaplot as ndp
75
+ >>> from matplotlib.figure import Figure
76
+ >>> from numdaplot.plots.chart_layer import ChartLayer
77
+ >>> from numdaplot.plots.data.array_values import read_array_values
78
+ >>> from numdaplot.plots.drawing.heatmap_drawing import draw_heatmap_chart
79
+ >>> grid = ndp.Array.from_list([[1.0, 2.0], [3.0, None]])
80
+ >>> axes = Figure().add_subplot()
81
+ >>> drawn_chart = draw_heatmap_chart(axes, ChartLayer(ndp.HeatmapChart(), read_array_values(grid, "HeatmapChart")))
82
+ >>> axes.images[0].get_array().mask.tolist()
83
+ [[False, False], [False, True]]
84
+ """
85
+ chart = cast(HeatmapChart, layer.chart)
86
+ values = cast(ChartValues, layer.values)
87
+ grid = stack_columns(values.series)
88
+ shown_cells = fit_cells_to_axes(grid, axes, average_cells)
89
+ cells_are_merged = shown_cells is not grid
90
+ scale_name = SCALE_NAMES[chart.scale]
91
+ base_scale = matplotlib.colormaps[scale_name]
92
+ color_scale = base_scale.with_extremes(bad=GRID_COLOR)
93
+ lowest_color, highest_color = find_scale_limits(shown_cells, chart.scale)
94
+ cell_limits = find_cell_limits(grid)
95
+ # matplotlib paints the NaN cells with the color for missing values of the scale.
96
+ image = axes.imshow(
97
+ shown_cells,
98
+ cmap=color_scale,
99
+ vmin=lowest_color,
100
+ vmax=highest_color,
101
+ aspect=CELL_ASPECT,
102
+ interpolation=CELL_INTERPOLATION,
103
+ extent=cell_limits,
104
+ )
105
+ place_column_names(axes, values.series)
106
+ place_categories(axes, values.positions, True)
107
+ hide_frame(axes)
108
+ scale_label = ""
109
+ if values.value_name is not None:
110
+ scale_label = values.value_name
111
+
112
+ add_color_bar(axes, image, scale_label, shown_cells)
113
+ values_are_asked = chart.values == CellValues.SHOWN
114
+ if cells_are_merged:
115
+ warn_merged_cells(grid, values_are_asked)
116
+ elif values_are_asked:
117
+ write_cell_values(axes, image, grid)
118
+
119
+ y_label = find_position_label(values.positions)
120
+ drawn_chart = DrawnChart(COLUMN_LABEL, y_label, False, GridAxes.NONE, None)
121
+
122
+ return drawn_chart
123
+
124
+
125
+ def warn_merged_cells(grid: NDArray[numpy.float64], values_are_asked: bool) -> None:
126
+ """
127
+ Warn that a heatmap shows the mean of its cells, and that their values are not written when they were asked for.
128
+
129
+ .. versionadded:: 0.1.0
130
+
131
+ Parameters
132
+ ----------
133
+ grid
134
+ The cells before they are merged.
135
+ values_are_asked
136
+ True when the chart asks for the values of the cells to be written.
137
+
138
+ Warns
139
+ -----
140
+ ReadabilityWarning
141
+ Always.
142
+
143
+ Examples
144
+ --------
145
+ >>> import numpy
146
+ >>> import warnings
147
+ >>> from numdaplot.plots.drawing.heatmap_drawing import warn_merged_cells
148
+ >>> with warnings.catch_warnings(record=True) as caught_warnings:
149
+ ... warnings.simplefilter("always")
150
+ ... warn_merged_cells(numpy.zeros((3000, 2)), False)
151
+ >>> str(caught_warnings[0].message).startswith("A HeatmapChart with 3000 rows and 2 columns")
152
+ True
153
+ """
154
+ row_count, column_count = grid.shape
155
+ message = MERGED_CELLS_MESSAGE.format(row_count=row_count, column_count=column_count)
156
+ if values_are_asked:
157
+ message = message + UNWRITTEN_VALUES_MESSAGE
158
+
159
+ warnings.warn(message, ReadabilityWarning, skip_file_prefixes=INTERNAL_FILES)
160
+
161
+
162
+ def stack_columns(series_list: list[Series]) -> NDArray[numpy.float64]:
163
+ """
164
+ Return the columns of a chart side by side, as a grid of one row per row and one column per column.
165
+
166
+ .. versionadded:: 0.1.0
167
+
168
+ Parameters
169
+ ----------
170
+ series_list
171
+ The columns, each with one number per row.
172
+
173
+ Returns
174
+ -------
175
+ NDArray[numpy.float64]
176
+ The grid of numbers, NaN where a value is missing.
177
+
178
+ Examples
179
+ --------
180
+ >>> import numpy
181
+ >>> from numdaplot.plots.data.chart_values import Series
182
+ >>> from numdaplot.plots.drawing.heatmap_drawing import stack_columns
183
+ >>> stack_columns([Series("jan", numpy.array([1.0, 2.0])), Series("feb", numpy.array([3.0, 4.0]))]).tolist()
184
+ [[1.0, 3.0], [2.0, 4.0]]
185
+ """
186
+ columns = [series.values for series in series_list]
187
+ grid = numpy.column_stack(columns)
188
+
189
+ return grid
190
+
191
+
192
+ def place_column_names(axes: Axes, series_list: list[Series]) -> None:
193
+ """
194
+ Label each column of cells with its name along the horizontal axis.
195
+
196
+ .. versionadded:: 0.1.0
197
+
198
+ Parameters
199
+ ----------
200
+ axes
201
+ The matplotlib axes drawn on.
202
+ series_list
203
+ The columns, in the order of the cells.
204
+
205
+ Examples
206
+ --------
207
+ >>> import numpy
208
+ >>> from matplotlib.figure import Figure
209
+ >>> from numdaplot.plots.data.chart_values import Series
210
+ >>> from numdaplot.plots.drawing.heatmap_drawing import place_column_names
211
+ >>> axes = Figure().add_subplot()
212
+ >>> place_column_names(axes, [Series("jan", numpy.array([1.0])), Series("feb", numpy.array([2.0]))])
213
+ >>> [label.get_text() for label in axes.get_xticklabels()]
214
+ ['jan', 'feb']
215
+ """
216
+ column_names = [series.name for series in series_list]
217
+ column_count = len(column_names)
218
+ coordinates = numpy.arange(column_count, dtype=numpy.float64)
219
+ set_fixed_labels(axes.xaxis, coordinates, column_names)
220
+
221
+
222
+ def hide_frame(axes: Axes) -> None:
223
+ """
224
+ Hide the lines framing the axes and their tick marks, the cells drawing their own edges.
225
+
226
+ .. versionadded:: 0.1.0
227
+
228
+ Parameters
229
+ ----------
230
+ axes
231
+ The matplotlib axes drawn on.
232
+
233
+ Examples
234
+ --------
235
+ >>> from matplotlib.figure import Figure
236
+ >>> from numdaplot.plots.drawing.heatmap_drawing import hide_frame
237
+ >>> axes = Figure().add_subplot()
238
+ >>> hide_frame(axes)
239
+ >>> axes.spines["left"].get_visible()
240
+ False
241
+ """
242
+ for spine in axes.spines.values():
243
+ spine.set_visible(False)
244
+
245
+ axes.tick_params(length=0)
246
+
247
+
248
+ def write_cell_values(axes: Axes, image: AxesImage, grid: NDArray[numpy.float64]) -> None:
249
+ """
250
+ Write the value of each cell inside it, in black or white to stay readable over its color.
251
+
252
+ A missing value writes nothing.
253
+
254
+ .. versionadded:: 0.1.0
255
+
256
+ Parameters
257
+ ----------
258
+ axes
259
+ The matplotlib axes drawn on.
260
+ image
261
+ The colored cells.
262
+ grid
263
+ The numbers of the cells, NaN where a value is missing.
264
+
265
+ Examples
266
+ --------
267
+ >>> import numpy
268
+ >>> from matplotlib.figure import Figure
269
+ >>> from numdaplot.plots.drawing.heatmap_drawing import write_cell_values
270
+ >>> axes = Figure().add_subplot()
271
+ >>> grid = numpy.array([[1.25, numpy.nan, 3.0]])
272
+ >>> write_cell_values(axes, axes.imshow(grid), grid)
273
+ >>> [text.get_text() for text in axes.texts]
274
+ ['1.25', '3']
275
+ """
276
+ # Some versions of the matplotlib stubs leave the colors given by to_rgba untyped.
277
+ cell_colors = cast(NDArray[numpy.float64], image.to_rgba(grid))
278
+
279
+ for (row, column), number in numpy.ndenumerate(grid):
280
+ if numpy.isnan(number):
281
+ continue
282
+
283
+ cell_color = cell_colors[row, column].tolist()
284
+ text_color = choose_text_color(cell_color)
285
+ cell_text = format_cell_value(number)
286
+ axes.text(column, row, cell_text, color=text_color, horizontalalignment=CENTERED, verticalalignment=CENTERED)
287
+
288
+
289
+ def format_cell_value(number: float) -> str:
290
+ """
291
+ Return the text of a cell value, with at most two decimals and no trailing zero.
292
+
293
+ .. versionadded:: 0.1.0
294
+
295
+ Parameters
296
+ ----------
297
+ number
298
+ The value of the cell.
299
+
300
+ Returns
301
+ -------
302
+ str
303
+ The value rounded to two decimals.
304
+
305
+ Examples
306
+ --------
307
+ >>> from numdaplot.plots.drawing.heatmap_drawing import format_cell_value
308
+ >>> format_cell_value(12.3456), format_cell_value(4.0)
309
+ ('12.35', '4')
310
+ """
311
+ cell_text = numpy.format_float_positional(number, precision=CELL_DECIMALS, trim=TRIMMED_ZEROS)
312
+
313
+ return cell_text
@@ -0,0 +1,350 @@
1
+ """
2
+ Drawing of a HistogramChart.
3
+
4
+ .. versionadded:: 0.1.0
5
+ """
6
+
7
+ # The matplotlib stubs leave the keyword arguments of most drawing methods untyped.
8
+ # pyright: reportUnknownMemberType=false
9
+
10
+ import math
11
+ from datetime import timedelta
12
+ from typing import cast
13
+
14
+ import numpy
15
+ from matplotlib.axes import Axes
16
+ from numpy.typing import NDArray
17
+
18
+ from numdaplot.data_types.type import Type
19
+ from numdaplot.errors.incompatible_types_error import IncompatibleTypesError
20
+ from numdaplot.plots.chart_layer import ChartLayer
21
+ from numdaplot.plots.charts.bin_count import BinCount
22
+ from numdaplot.plots.charts.bin_width import BinWidth
23
+ from numdaplot.plots.charts.histogram_chart import HistogramChart
24
+ from numdaplot.plots.data.sample_values import SampleValues, drop_missing_numbers
25
+ from numdaplot.plots.drawing.drawn_chart import DrawnChart
26
+ from numdaplot.plots.drawing.grid_axes import GridAxes
27
+ from numdaplot.plots.drawing.plot_theme import BACKGROUND_COLOR
28
+ from numdaplot.plots.drawing.series_colors import choose_series_colors
29
+ from numdaplot.plots.drawing.time_axis import measures_times, place_hour_ticks
30
+ from numdaplot.plots.drawing.whole_numbers import place_whole_ticks
31
+ from numdaplot.ratios.measure import Measure
32
+
33
+ MEASURE_LABELS = {
34
+ Measure.COUNT: "Count",
35
+ Measure.RATIO: "Ratio",
36
+ }
37
+ SINGLE_OPACITY = 1.0
38
+ OVERLAID_OPACITY = 0.5
39
+ BIN_EDGE_WIDTH = 0.8
40
+ # Each bar starts at the left edge of its bin.
41
+ BIN_ALIGNMENT = "edge"
42
+ DEFAULT_BIN_COUNT = 10
43
+ HOURS_PER_DAY = 24
44
+ DAY_EDGE_COUNT = HOURS_PER_DAY + 1
45
+ ONE_HOUR = timedelta(hours=1)
46
+ NUMBER_WIDTH_TYPE = Type.FLOAT64
47
+ DURATION_WIDTH_TYPE = Type.DURATION
48
+ WIDTH_OPERATION = "BinWidth"
49
+
50
+
51
+ def draw_histogram_chart(axes: Axes, layer: ChartLayer) -> DrawnChart:
52
+ """
53
+ Draw how many values of each column fall in each bin, the columns sharing the same bins.
54
+
55
+ Several columns are drawn over each other, half transparent. Missing values are left out.
56
+
57
+ .. versionadded:: 0.1.0
58
+
59
+ Parameters
60
+ ----------
61
+ axes
62
+ The matplotlib axes drawn on.
63
+ layer
64
+ A HistogramChart and its columns.
65
+
66
+ Returns
67
+ -------
68
+ DrawnChart
69
+ The single column as default label of the values, ``"Count"`` or ``"Ratio"`` as label of the other axis,
70
+ and grid lines across that axis only.
71
+
72
+ Raises
73
+ ------
74
+ InvalidColorCountError
75
+ When the colors of the chart are not one per column.
76
+
77
+ Examples
78
+ --------
79
+ >>> import numdaplot as ndp
80
+ >>> from matplotlib.figure import Figure
81
+ >>> from numdaplot.plots.chart_layer import ChartLayer
82
+ >>> from numdaplot.plots.data.sample_values import read_sample_values
83
+ >>> from numdaplot.plots.drawing.histogram_drawing import draw_histogram_chart
84
+ >>> prices = ndp.Array.from_list([12.0, 13.0, 17.0, None])
85
+ >>> axes = Figure().add_subplot()
86
+ >>> samples = read_sample_values(prices, None, None, "HistogramChart")
87
+ >>> layer = ChartLayer(ndp.HistogramChart(bins=ndp.BinWidth(5.0)), samples)
88
+ >>> drawn_chart = draw_histogram_chart(axes, layer)
89
+ >>> [float(bar.get_height()) for bar in axes.patches]
90
+ [2.0, 1.0]
91
+ """
92
+ chart = cast(HistogramChart, layer.chart)
93
+ values = cast(SampleValues, layer.values)
94
+ series_count = len(values.series)
95
+ color_codes = choose_series_colors(chart.colors, series_count)
96
+ samples = [drop_missing_numbers(series.values) for series in values.series]
97
+ all_numbers = numpy.concatenate(samples)
98
+ bin_edges = find_bin_edges(all_numbers, chart.bins, values.value_type)
99
+ bin_starts = bin_edges[:-1]
100
+ bin_widths = numpy.diff(bin_edges)
101
+ opacity = SINGLE_OPACITY
102
+ if series_count > 1:
103
+ opacity = OVERLAID_OPACITY
104
+
105
+ bin_counts = list[NDArray[numpy.float64]]()
106
+
107
+ for i, series in enumerate(values.series):
108
+ weights = find_bin_weights(samples[i], chart.measure)
109
+ counts, _ = numpy.histogram(samples[i], bins=bin_edges, weights=weights)
110
+ series_counts = numpy.asarray(counts, dtype=numpy.float64)
111
+ axes.bar(
112
+ bin_starts,
113
+ series_counts,
114
+ width=bin_widths,
115
+ align=BIN_ALIGNMENT,
116
+ color=color_codes[i],
117
+ alpha=opacity,
118
+ label=series.name,
119
+ edgecolor=BACKGROUND_COLOR,
120
+ linewidth=BIN_EDGE_WIDTH,
121
+ )
122
+ bin_counts.append(series_counts)
123
+
124
+ all_counts = numpy.concatenate(bin_counts)
125
+ place_whole_ticks(axes.yaxis, all_counts)
126
+
127
+ is_time = measures_times(values.value_type)
128
+ if is_time:
129
+ place_hour_ticks(axes.xaxis, bin_edges)
130
+
131
+ measure_label = MEASURE_LABELS[chart.measure]
132
+ drawn_chart = DrawnChart(values.value_name, measure_label, False, GridAxes.VALUES, None)
133
+
134
+ return drawn_chart
135
+
136
+
137
+ def require_bins_on_values(bins: BinCount | BinWidth | None, value_type: Type) -> None:
138
+ """
139
+ Check that the width of the bins of a histogram is a number for numbers and a duration for times of day.
140
+
141
+ .. versionadded:: 0.1.0
142
+
143
+ Parameters
144
+ ----------
145
+ bins
146
+ The bins of the HistogramChart, None for the default ones.
147
+ value_type
148
+ The type of the values drawn.
149
+
150
+ Raises
151
+ ------
152
+ IncompatibleTypesError
153
+ When a number gives the width of bins of times of day, or a duration the width of bins of numbers.
154
+
155
+ Examples
156
+ --------
157
+ >>> from datetime import timedelta
158
+ >>> import numdaplot as ndp
159
+ >>> from numdaplot.plots.drawing.histogram_drawing import require_bins_on_values
160
+ >>> try:
161
+ ... require_bins_on_values(ndp.BinWidth(timedelta(hours=1)), ndp.Type.FLOAT64)
162
+ ... except ndp.IncompatibleTypesError as error:
163
+ ... print(error)
164
+ Cannot apply BinWidth to DURATION and FLOAT64.
165
+ """
166
+ if not isinstance(bins, BinWidth):
167
+ return
168
+
169
+ is_time = measures_times(value_type)
170
+ is_duration = isinstance(bins.width, timedelta)
171
+ if is_duration == is_time:
172
+ return
173
+
174
+ width_type = NUMBER_WIDTH_TYPE
175
+ if is_duration:
176
+ width_type = DURATION_WIDTH_TYPE
177
+
178
+ raise IncompatibleTypesError(WIDTH_OPERATION, [width_type.name, value_type.name])
179
+
180
+
181
+ def find_bin_edges(
182
+ numbers: NDArray[numpy.float64], bins: BinCount | BinWidth | None, value_type: Type
183
+ ) -> NDArray[numpy.float64]:
184
+ """
185
+ Return the edges of the bins of a histogram.
186
+
187
+ .. versionadded:: 0.1.0
188
+
189
+ Parameters
190
+ ----------
191
+ numbers
192
+ Every number drawn, of every column, none missing, a time of day being its hours since midnight.
193
+ bins
194
+ The number of bins, spread from the smallest to the largest number, or their width, checked against the
195
+ values. None gives 10 bins for numbers and one bin per hour from 00:00 to 24:00 for times of day.
196
+ value_type
197
+ The type of the values drawn.
198
+
199
+ Returns
200
+ -------
201
+ NDArray[numpy.float64]
202
+ One edge more than there are bins, in hours for times of day.
203
+
204
+ Examples
205
+ --------
206
+ >>> import numdaplot as ndp
207
+ >>> import numpy
208
+ >>> from numdaplot.plots.drawing.histogram_drawing import find_bin_edges
209
+ >>> find_bin_edges(numpy.array([12.0, 20.0]), ndp.BinCount(4), ndp.Type.FLOAT64)
210
+ array([12., 14., 16., 18., 20.])
211
+ >>> len(find_bin_edges(numpy.array([8.5]), None, ndp.Type.TIME))
212
+ 25
213
+ """
214
+ is_time = measures_times(value_type)
215
+ uses_day_edges = bins is None and is_time
216
+ if uses_day_edges:
217
+ day_edges = numpy.arange(DAY_EDGE_COUNT, dtype=numpy.float64)
218
+ return day_edges
219
+
220
+ if bins is None:
221
+ bins = BinCount(DEFAULT_BIN_COUNT)
222
+
223
+ if isinstance(bins, BinWidth):
224
+ width = read_width_hours(bins)
225
+ width_edges = find_width_edges(numbers, width)
226
+ return width_edges
227
+
228
+ count_edges = numpy.histogram_bin_edges(numbers, bins=bins.count)
229
+
230
+ return count_edges
231
+
232
+
233
+ def read_width_hours(bins: BinWidth) -> float:
234
+ """
235
+ Return the width of bins as a number, a duration being counted in hours.
236
+
237
+ .. versionadded:: 0.1.0
238
+
239
+ Parameters
240
+ ----------
241
+ bins
242
+ The width of the bins.
243
+
244
+ Returns
245
+ -------
246
+ float
247
+ The width of bins of numbers, or the hours of a duration.
248
+
249
+ Examples
250
+ --------
251
+ >>> from datetime import timedelta
252
+ >>> import numdaplot as ndp
253
+ >>> from numdaplot.plots.drawing.histogram_drawing import read_width_hours
254
+ >>> read_width_hours(ndp.BinWidth(timedelta(minutes=30))), read_width_hours(ndp.BinWidth(2.5))
255
+ (0.5, 2.5)
256
+ """
257
+ if isinstance(bins.width, timedelta):
258
+ width_hours = bins.width / ONE_HOUR
259
+ return width_hours
260
+
261
+ return bins.width
262
+
263
+
264
+ def find_width_edges(numbers: NDArray[numpy.float64], width: float) -> NDArray[numpy.float64]:
265
+ """
266
+ Return the edges of bins of a given width, each edge being a multiple of the width.
267
+
268
+ The first edge is the largest multiple not above the smallest number, and the bins go on until the largest
269
+ number. Without numbers, a single bin starts at 0.
270
+
271
+ .. versionadded:: 0.1.0
272
+
273
+ Parameters
274
+ ----------
275
+ numbers
276
+ Every number drawn, none missing.
277
+ width
278
+ The width of each bin, above 0.
279
+
280
+ Returns
281
+ -------
282
+ NDArray[numpy.float64]
283
+ The edges, at least two.
284
+
285
+ Examples
286
+ --------
287
+ >>> import numpy
288
+ >>> from numdaplot.plots.drawing.histogram_drawing import find_width_edges
289
+ >>> find_width_edges(numpy.array([12.0, 21.0]), 5.0)
290
+ array([10., 15., 20., 25.])
291
+ """
292
+ smallest_number = 0.0
293
+ largest_number = 0.0
294
+ number_count = len(numbers)
295
+ if number_count > 0:
296
+ smallest_number = float(numbers.min())
297
+ largest_number = float(numbers.max())
298
+
299
+ first_width_count = math.floor(smallest_number / width)
300
+ first_edge = first_width_count * width
301
+ covered_widths = (largest_number - first_edge) / width
302
+ bin_count = math.ceil(covered_widths)
303
+ bin_count = max(bin_count, 1)
304
+ edge_count = bin_count + 1
305
+ edge_numbers = numpy.arange(edge_count, dtype=numpy.float64)
306
+ edge_offsets = edge_numbers * width
307
+ shifted_offsets = first_edge + edge_offsets
308
+ # Some versions of the numpy stubs widen the sum of float64 values to any floating type.
309
+ edges = numpy.asarray(shifted_offsets, dtype=numpy.float64)
310
+
311
+ return edges
312
+
313
+
314
+ def find_bin_weights(numbers: NDArray[numpy.float64], measure: Measure) -> NDArray[numpy.float64] | None:
315
+ """
316
+ Return how much each number weighs in its bin.
317
+
318
+ .. versionadded:: 0.1.0
319
+
320
+ Parameters
321
+ ----------
322
+ numbers
323
+ The numbers of one column, none missing.
324
+ measure
325
+ ``Measure.COUNT`` to count the numbers, ``Measure.RATIO`` for their share of the column.
326
+
327
+ Returns
328
+ -------
329
+ NDArray[numpy.float64] or None
330
+ None to count each number once, or one share per number, the shares adding up to 1.
331
+
332
+ Examples
333
+ --------
334
+ >>> import numdaplot as ndp
335
+ >>> import numpy
336
+ >>> from numdaplot.plots.drawing.histogram_drawing import find_bin_weights
337
+ >>> find_bin_weights(numpy.array([3.0, 5.0, 8.0, 9.0]), ndp.Measure.RATIO)
338
+ array([0.25, 0.25, 0.25, 0.25])
339
+ """
340
+ number_count = len(numbers)
341
+ is_counted = measure == Measure.COUNT
342
+ has_no_numbers = number_count == 0
343
+ weighs_one = is_counted or has_no_numbers
344
+ if weighs_one:
345
+ return None
346
+
347
+ share = 1 / number_count
348
+ weights = numpy.full(number_count, share)
349
+
350
+ return weights