MatplotLibAPI 3.2.21__py3-none-any.whl → 4.0.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 (51) hide show
  1. MatplotLibAPI/__init__.py +4 -86
  2. MatplotLibAPI/accessor.py +519 -196
  3. MatplotLibAPI/area.py +177 -0
  4. MatplotLibAPI/bar.py +185 -0
  5. MatplotLibAPI/base_plot.py +88 -0
  6. MatplotLibAPI/box_violin.py +180 -0
  7. MatplotLibAPI/bubble.py +568 -0
  8. MatplotLibAPI/{Composite.py → composite.py} +127 -106
  9. MatplotLibAPI/heatmap.py +223 -0
  10. MatplotLibAPI/histogram.py +170 -0
  11. MatplotLibAPI/mcp/__init__.py +17 -0
  12. MatplotLibAPI/mcp/metadata.py +90 -0
  13. MatplotLibAPI/mcp/renderers.py +45 -0
  14. MatplotLibAPI/mcp_server.py +626 -0
  15. MatplotLibAPI/network/__init__.py +28 -0
  16. MatplotLibAPI/network/constants.py +22 -0
  17. MatplotLibAPI/network/core.py +1360 -0
  18. MatplotLibAPI/network/plot.py +597 -0
  19. MatplotLibAPI/network/scaling.py +56 -0
  20. MatplotLibAPI/pie.py +154 -0
  21. MatplotLibAPI/pivot.py +274 -0
  22. MatplotLibAPI/sankey.py +99 -0
  23. MatplotLibAPI/{StyleTemplate.py → style_template.py} +27 -22
  24. MatplotLibAPI/sunburst.py +139 -0
  25. MatplotLibAPI/{Table.py → table.py} +112 -87
  26. MatplotLibAPI/{Timeserie.py → timeserie.py} +98 -42
  27. MatplotLibAPI/{Treemap.py → treemap.py} +43 -55
  28. MatplotLibAPI/typing.py +12 -0
  29. MatplotLibAPI/{_visualization_utils.py → utils.py} +7 -13
  30. MatplotLibAPI/waffle.py +173 -0
  31. MatplotLibAPI/word_cloud.py +489 -0
  32. {matplotlibapi-3.2.21.dist-info → matplotlibapi-4.0.0.dist-info}/METADATA +98 -9
  33. matplotlibapi-4.0.0.dist-info/RECORD +36 -0
  34. {matplotlibapi-3.2.21.dist-info → matplotlibapi-4.0.0.dist-info}/WHEEL +1 -1
  35. matplotlibapi-4.0.0.dist-info/entry_points.txt +2 -0
  36. MatplotLibAPI/Area.py +0 -80
  37. MatplotLibAPI/Bar.py +0 -83
  38. MatplotLibAPI/BoxViolin.py +0 -75
  39. MatplotLibAPI/Bubble.py +0 -458
  40. MatplotLibAPI/Heatmap.py +0 -121
  41. MatplotLibAPI/Histogram.py +0 -73
  42. MatplotLibAPI/Network.py +0 -989
  43. MatplotLibAPI/Pie.py +0 -70
  44. MatplotLibAPI/Pivot.py +0 -134
  45. MatplotLibAPI/Sankey.py +0 -46
  46. MatplotLibAPI/Sunburst.py +0 -89
  47. MatplotLibAPI/Waffle.py +0 -86
  48. MatplotLibAPI/Wordcloud.py +0 -373
  49. MatplotLibAPI/_typing.py +0 -17
  50. matplotlibapi-3.2.21.dist-info/RECORD +0 -26
  51. {matplotlibapi-3.2.21.dist-info → matplotlibapi-4.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,568 @@
1
+ """Bubble chart plotting helpers.
2
+
3
+ Provides a Bubble class to create and render bubble charts using seaborn and matplotlib,
4
+ with customizable styling via `StyleTemplate`.
5
+ """
6
+
7
+ from typing import Any, Dict, Optional, Tuple, cast
8
+
9
+ import matplotlib.pyplot as plt
10
+ import pandas as pd
11
+ from pandas.api.extensions import register_dataframe_accessor
12
+ import seaborn as sns
13
+ from matplotlib.axes import Axes
14
+ from matplotlib.figure import Figure
15
+ from matplotlib.ticker import NullLocator
16
+
17
+ from .base_plot import BasePlot
18
+
19
+ from .style_template import (
20
+ BUBBLE_STYLE_TEMPLATE,
21
+ FIG_SIZE,
22
+ MAX_RESULTS,
23
+ TITLE_SCALE_FACTOR,
24
+ StyleTemplate,
25
+ format_func,
26
+ generate_ticks,
27
+ validate_dataframe,
28
+ DynamicFuncFormatter,
29
+ FormatterFunc,
30
+ )
31
+
32
+ __all__ = ["BUBBLE_STYLE_TEMPLATE", "Bubble"]
33
+
34
+
35
+ @register_dataframe_accessor("bubble")
36
+ class Bubble(BasePlot):
37
+ """Bubble chart plot implementing the BasePlot interface.
38
+
39
+ This class provides methods to plot bubble charts on existing or new
40
+ Matplotlib figures with customizable styling.
41
+
42
+ Methods
43
+ -------
44
+ aplot
45
+ Plot a bubble chart on existing Matplotlib axes.
46
+ fplot
47
+ Plot a bubble chart on a new Matplotlib figure.
48
+ """
49
+
50
+ def __init__(
51
+ self,
52
+ pd_df: pd.DataFrame,
53
+ label: str,
54
+ x: str,
55
+ y: str,
56
+ z: str,
57
+ sort_by: Optional[str] = None,
58
+ ascending: bool = False,
59
+ max_values: int = MAX_RESULTS,
60
+ center_to_mean: bool = False,
61
+ ):
62
+ """Initialize the Bubble plot accessor."""
63
+ plot_df = self._prepare_data(
64
+ pd_df,
65
+ label=label,
66
+ x=x,
67
+ y=y,
68
+ z=z,
69
+ sort_by=sort_by,
70
+ ascending=ascending,
71
+ max_values=max_values,
72
+ center_to_mean=center_to_mean,
73
+ )
74
+ self.x = x
75
+ self.y = y
76
+ self.z = z
77
+ self.label = label
78
+ super().__init__(plot_df)
79
+
80
+ @staticmethod
81
+ def _prepare_data(
82
+ pd_df: pd.DataFrame,
83
+ label: str,
84
+ x: str,
85
+ y: str,
86
+ z: str,
87
+ sort_by: Optional[str] = None,
88
+ ascending: bool = False,
89
+ max_values: int = MAX_RESULTS,
90
+ center_to_mean: bool = False,
91
+ ) -> pd.DataFrame:
92
+ """Prepare data for bubble chart.
93
+
94
+ Parameters
95
+ ----------
96
+ pd_df : pd.DataFrame
97
+ Input DataFrame.
98
+ label : str
99
+ Column name for bubble labels.
100
+ x : str
101
+ Column name for x-axis values.
102
+ y : str
103
+ Column name for y-axis values.
104
+ z : str
105
+ Column name for bubble sizes.
106
+ sort_by : Optional[str]
107
+ Column to sort by.
108
+ ascending : bool
109
+ Sort order.
110
+ max_values : int
111
+ Maximum number of bubbles to display.
112
+ center_to_mean : bool
113
+ Whether to center x-axis values around the mean.
114
+
115
+
116
+ Returns
117
+ -------
118
+ pd.DataFrame
119
+ Prepared DataFrame for plotting.
120
+
121
+ Raises
122
+ ------
123
+ AttributeError
124
+ If required columns are missing from the DataFrame.
125
+ """
126
+ validate_dataframe(pd_df, cols=[label, x, y, z], sort_by=sort_by)
127
+ sort_col = sort_by or z
128
+
129
+ plot_df = (
130
+ pd_df[[label, x, y, z]]
131
+ .sort_values(by=[sort_col], ascending=ascending) # type: ignore
132
+ .head(max_values)
133
+ .copy()
134
+ )
135
+
136
+ if center_to_mean:
137
+ plot_df[x] -= plot_df[x].mean()
138
+
139
+ plot_df["quintile"] = pd.qcut(plot_df[z], 5, labels=False, duplicates="drop")
140
+ plot_df[f"{x}_mean"] = plot_df[x].mean()
141
+ plot_df[f"{y}_mean"] = plot_df[y].mean()
142
+ plot_df[f"{z}_mean"] = plot_df[z].mean()
143
+ return plot_df
144
+
145
+ @staticmethod
146
+ def _setup_axes(
147
+ ax: Axes,
148
+ style: StyleTemplate,
149
+ pd_df: pd.DataFrame,
150
+ x: str,
151
+ y: str,
152
+ format_funcs: Optional[Dict[str, Optional[FormatterFunc]]],
153
+ ) -> None:
154
+ """Configure axes for the bubble chart.
155
+
156
+ Parameters
157
+ ----------
158
+ ax : Axes
159
+ Matplotlib axes object.
160
+ style : StyleTemplate
161
+ Styling for the plot.
162
+ pd_df : pd.DataFrame
163
+ DataFrame used for plotting.
164
+ x : str
165
+ Column name for x-axis values.
166
+ y : str
167
+ Column name for y-axis values.
168
+ format_funcs : Optional[Dict[str, Optional[FormatterFunc]]]
169
+ Functions to format axis tick labels.
170
+ """
171
+ ax.set_facecolor(style.background_color)
172
+
173
+ if style.xscale:
174
+ ax.set(xscale=style.xscale)
175
+ if style.yscale:
176
+ ax.set(yscale=style.yscale)
177
+
178
+ # X-axis ticks and formatting
179
+ x_min, x_max = cast(float, pd_df[x].min()), cast(float, pd_df[x].max())
180
+ ax.xaxis.set_ticks(
181
+ generate_ticks(
182
+ x_min, x_max, num_ticks=style.x_ticks
183
+ ) # pyright: ignore[reportArgumentType]
184
+ )
185
+ ax.xaxis.grid(True, "major", linewidth=0.5, color=style.font_color)
186
+ if format_funcs and (fmt_x := format_funcs.get(x)):
187
+ ax.xaxis.set_major_formatter(DynamicFuncFormatter(fmt_x))
188
+
189
+ # Y-axis ticks and formatting
190
+ y_min, y_max = cast(float, pd_df[y].min()), cast(float, pd_df[y].max())
191
+ ax.yaxis.set_ticks(
192
+ generate_ticks(
193
+ y_min, y_max, num_ticks=style.y_ticks
194
+ ) # pyright: ignore[reportArgumentType]
195
+ )
196
+ if style.yscale == "log":
197
+ ax.yaxis.set_minor_locator(NullLocator())
198
+ else:
199
+ ax.minorticks_off()
200
+ ax.yaxis.grid(True, "major", linewidth=0.5, color=style.font_color)
201
+ if format_funcs and (fmt_y := format_funcs.get(y)):
202
+ ax.yaxis.set_major_formatter(DynamicFuncFormatter(fmt_y))
203
+
204
+ ax.tick_params(
205
+ axis="both",
206
+ which="major",
207
+ colors=style.font_color,
208
+ labelsize=style.font_size,
209
+ )
210
+
211
+ @staticmethod
212
+ def _draw_bubbles(
213
+ ax: Axes, plot_df: pd.DataFrame, x: str, y: str, z: str, style: StyleTemplate
214
+ ) -> None:
215
+ """Draw bubbles on the axes.
216
+
217
+ Parameters
218
+ ----------
219
+ ax : Axes
220
+ Matplotlib axes object.
221
+ plot_df : pd.DataFrame
222
+ DataFrame with data for plotting.
223
+ x : str
224
+ Column name for x-axis values.
225
+ y : str
226
+ Column name for y-axis values.
227
+ z : str
228
+ Column name for bubble sizes.
229
+ style : StyleTemplate
230
+ Styling for the plot.
231
+ """
232
+ sns.scatterplot(
233
+ data=plot_df,
234
+ x=x,
235
+ y=y,
236
+ size=z,
237
+ hue="quintile",
238
+ sizes=(100, 2000),
239
+ legend=False,
240
+ palette=sns.color_palette(style.palette, as_cmap=True),
241
+ edgecolor=style.background_color,
242
+ ax=ax,
243
+ )
244
+
245
+ @staticmethod
246
+ def _draw_labels(
247
+ ax: Axes,
248
+ plot_df: pd.DataFrame,
249
+ label: str,
250
+ x: str,
251
+ y: str,
252
+ style: StyleTemplate,
253
+ format_funcs: Optional[Dict[str, Optional[FormatterFunc]]],
254
+ ) -> None:
255
+ """Draw labels for each bubble.
256
+
257
+ Parameters
258
+ ----------
259
+ ax : Axes
260
+ Matplotlib axes object.
261
+ plot_df : pd.DataFrame
262
+ DataFrame with data for plotting.
263
+ label : str
264
+ Column name for bubble labels.
265
+ x : str
266
+ Column name for x-axis values.
267
+ y : str
268
+ Column name for y-axis values.
269
+ style : StyleTemplate
270
+ Styling for the plot.
271
+ format_funcs : Optional[Dict[str, Optional[FormatterFunc]]]
272
+ Functions to format bubble labels.
273
+ """
274
+ for _, row in plot_df.iterrows():
275
+ x_val, y_val, label_val = row[x], row[y], str(row[label])
276
+ if format_funcs and (fmt_label := format_funcs.get(label)):
277
+ label_val = fmt_label(label_val, None)
278
+ quintile = cast(int, row["quintile"])
279
+ ax.text(
280
+ cast(float, x_val),
281
+ cast(float, y_val),
282
+ label_val,
283
+ ha="center",
284
+ fontsize=style.font_mapping.get(quintile, style.font_size),
285
+ color=style.font_color,
286
+ )
287
+
288
+ @staticmethod
289
+ def _draw_lines(
290
+ ax: Axes,
291
+ plot_df: pd.DataFrame,
292
+ x: str,
293
+ y: str,
294
+ hline: bool,
295
+ vline: bool,
296
+ style: StyleTemplate,
297
+ ) -> None:
298
+ """Draw horizontal and vertical mean lines.
299
+
300
+ Parameters
301
+ ----------
302
+ ax : Axes
303
+ Matplotlib axes object.
304
+ plot_df : pd.DataFrame
305
+ DataFrame with data for plotting.
306
+ x : str
307
+ Column name for x-axis values.
308
+ y : str
309
+ Column name for y-axis values.
310
+ hline : bool
311
+ Whether to draw a horizontal line at the mean of y.
312
+ vline : bool
313
+ Whether to draw a vertical line at the mean of x.
314
+ style : StyleTemplate
315
+ Styling for the plot.
316
+ """
317
+ if vline:
318
+ ax.axvline(
319
+ int(cast(float, plot_df[x].mean())),
320
+ linestyle="--",
321
+ color=style.font_color,
322
+ )
323
+ if hline:
324
+ ax.axhline(
325
+ int(cast(float, plot_df[y].mean())),
326
+ linestyle="--",
327
+ color=style.font_color,
328
+ )
329
+
330
+ def aplot(
331
+ self,
332
+ title: Optional[str] = None,
333
+ style: StyleTemplate = BUBBLE_STYLE_TEMPLATE,
334
+ hline: bool = False,
335
+ vline: bool = False,
336
+ ax: Optional[Axes] = None,
337
+ **kwargs: Any,
338
+ ) -> Axes:
339
+ """Plot a bubble chart on existing axes.
340
+
341
+ Parameters
342
+ ----------
343
+ pd_df : pd.DataFrame
344
+ DataFrame containing the data to plot.
345
+ label : str
346
+ Column name used for labeling bubbles.
347
+ x : str
348
+ Column name for x-axis values.
349
+ y : str
350
+ Column name for y-axis values.
351
+ z : str
352
+ Column name for bubble sizes.
353
+ title : str, optional
354
+ Plot title. The default is None.
355
+ style : StyleTemplate, optional
356
+ Plot styling. The default is `BUBBLE_STYLE_TEMPLATE`.
357
+ max_values : int, optional
358
+ Max number of rows to display. The default is `MAX_RESULTS`.
359
+ center_to_mean : bool, optional
360
+ Whether to center x values around their mean. The default is False.
361
+ sort_by : str, optional
362
+ Column to sort by before slicing. The default is None.
363
+ ascending : bool, optional
364
+ Sort order. The default is False.
365
+ hline : bool, optional
366
+ Whether to draw a horizontal line at the mean of y. The default is False.
367
+ vline : bool, optional
368
+ Whether to draw a vertical line at the mean of x. The default is False.
369
+ ax : Axes, optional
370
+ Existing matplotlib axes to use. If None, uses current axes.
371
+ **kwargs : Any
372
+ Additional keyword arguments (unused, for interface compatibility).
373
+
374
+ Returns
375
+ -------
376
+ Axes
377
+ The Matplotlib axes object with the bubble chart.
378
+
379
+ Raises
380
+ ------
381
+ AttributeError
382
+ If required columns are not in the DataFrame.
383
+
384
+ Examples
385
+ --------
386
+ >>> import pandas as pd
387
+ >>> import matplotlib.pyplot as plt
388
+ >>> from MatplotLibAPI import Bubble
389
+ >>> data = {
390
+ ... 'country': ['A', 'B', 'C', 'D'],
391
+ ... 'gdp_per_capita': [45000, 42000, 52000, 48000],
392
+ ... 'life_expectancy': [81, 78, 83, 82],
393
+ ... 'population': [10, 20, 5, 30]
394
+ ... }
395
+ >>> df = pd.DataFrame(data)
396
+ >>> fig, ax = plt.subplots()
397
+ >>> Bubble.aplot(df, label='country', x='gdp_per_capita',
398
+ ... y='life_expectancy', z='population', ax=ax)
399
+ """
400
+ if ax is None:
401
+ ax = cast(Axes, plt.gca())
402
+
403
+ format_funcs = format_func(
404
+ style.format_funcs, label=self.label, x=self.x, y=self.y, z=self.z
405
+ )
406
+
407
+ Bubble._setup_axes(ax, style, self._obj, self.x, self.y, format_funcs)
408
+
409
+ Bubble._draw_bubbles(ax, self._obj, self.x, self.y, self.z, style)
410
+ Bubble._draw_lines(ax, self._obj, self.x, self.y, hline, vline, style)
411
+ Bubble._draw_labels(
412
+ ax, self._obj, self.label, self.x, self.y, style, format_funcs
413
+ )
414
+
415
+ if title:
416
+ ax.set_title(
417
+ title,
418
+ color=style.font_color,
419
+ fontsize=style.font_size * TITLE_SCALE_FACTOR,
420
+ )
421
+
422
+ return ax
423
+
424
+ def fplot(
425
+ self,
426
+ title: Optional[str] = None,
427
+ style: StyleTemplate = BUBBLE_STYLE_TEMPLATE,
428
+ hline: bool = False,
429
+ vline: bool = False,
430
+ figsize: Tuple[float, float] = FIG_SIZE,
431
+ ) -> Figure:
432
+ """Plot a bubble chart on a new figure.
433
+
434
+ Parameters
435
+ ----------
436
+ pd_df : pd.DataFrame
437
+ DataFrame containing the data to plot.
438
+ label : str
439
+ Column name for bubble labels.
440
+ x : str
441
+ Column name for x-axis values.
442
+ y : str
443
+ Column name for y-axis values.
444
+ z : str
445
+ Column name for bubble sizes.
446
+ title : str, optional
447
+ Plot title. The default is None.
448
+ style : StyleTemplate, optional
449
+ Plot styling. The default is `BUBBLE_STYLE_TEMPLATE`.
450
+ max_values : int, optional
451
+ Max number of rows to display. The default is `MAX_RESULTS`.
452
+ center_to_mean : bool, optional
453
+ Whether to center x around its mean. The default is False.
454
+ sort_by : str, optional
455
+ Column to sort by. The default is None.
456
+ ascending : bool, optional
457
+ Sort order. The default is False.
458
+ hline : bool, optional
459
+ Draw horizontal line at mean y. The default is False.
460
+ vline : bool, optional
461
+ Draw vertical line at mean x. The default is False.
462
+ figsize : tuple[float, float], optional
463
+ Size of the figure. The default is FIG_SIZE.
464
+
465
+
466
+ Returns
467
+ -------
468
+ Figure
469
+ A matplotlib Figure object with the bubble chart.
470
+
471
+ Raises
472
+ ------
473
+ AttributeError
474
+ If required columns are not in the DataFrame.
475
+
476
+ Examples
477
+ --------
478
+ >>> import pandas as pd
479
+ >>> from MatplotLibAPI import Bubble
480
+ >>> data = {
481
+ ... 'country': ['A', 'B', 'C', 'D'],
482
+ ... 'gdp_per_capita': [45000, 42000, 52000, 48000],
483
+ ... 'life_expectancy': [81, 78, 83, 82],
484
+ ... 'population': [10, 20, 5, 30]
485
+ ... }
486
+ >>> df = pd.DataFrame(data)
487
+ >>> fig = Bubble.fplot(df, label='country', x='gdp_per_capita',
488
+ ... y='life_expectancy', z='population')
489
+ """
490
+ fig = Figure(
491
+ figsize=figsize,
492
+ facecolor=style.background_color,
493
+ edgecolor=style.background_color,
494
+ )
495
+ ax = Axes(fig=fig, facecolor=style.background_color)
496
+
497
+ self.aplot(
498
+ title=title,
499
+ style=style,
500
+ hline=hline,
501
+ vline=vline,
502
+ ax=ax,
503
+ )
504
+ return fig
505
+
506
+
507
+ def aplot_bubble(
508
+ pd_df: pd.DataFrame,
509
+ label: str,
510
+ x: str,
511
+ y: str,
512
+ z: str,
513
+ sort_by: Optional[str] = None,
514
+ ascending: bool = False,
515
+ max_values: int = MAX_RESULTS,
516
+ center_to_mean: bool = False,
517
+ title: Optional[str] = None,
518
+ style: StyleTemplate = BUBBLE_STYLE_TEMPLATE,
519
+ hline: bool = False,
520
+ vline: bool = False,
521
+ ax: Optional[Axes] = None,
522
+ **kwargs: Any,
523
+ ) -> Axes:
524
+ """Plot a bubble chart on existing axes."""
525
+ return Bubble(
526
+ pd_df=pd_df,
527
+ label=label,
528
+ x=x,
529
+ y=y,
530
+ z=z,
531
+ sort_by=sort_by,
532
+ ascending=ascending,
533
+ max_values=max_values,
534
+ center_to_mean=center_to_mean,
535
+ ).aplot(title=title, style=style, hline=hline, vline=vline, ax=ax, **kwargs)
536
+
537
+
538
+ def fplot_bubble(
539
+ pd_df: pd.DataFrame,
540
+ label: str,
541
+ x: str,
542
+ y: str,
543
+ z: str,
544
+ sort_by: Optional[str] = None,
545
+ ascending: bool = False,
546
+ max_values: int = MAX_RESULTS,
547
+ center_to_mean: bool = False,
548
+ title: Optional[str] = None,
549
+ style: StyleTemplate = BUBBLE_STYLE_TEMPLATE,
550
+ hline: bool = False,
551
+ vline: bool = False,
552
+ figsize: Tuple[float, float] = FIG_SIZE,
553
+ **kwargs: Any,
554
+ ) -> Figure:
555
+ """Plot a bubble chart on a new figure."""
556
+ return Bubble(
557
+ pd_df=pd_df,
558
+ label=label,
559
+ x=x,
560
+ y=y,
561
+ z=z,
562
+ sort_by=sort_by,
563
+ ascending=ascending,
564
+ max_values=max_values,
565
+ center_to_mean=center_to_mean,
566
+ ).fplot(
567
+ title=title, style=style, hline=hline, vline=vline, figsize=figsize, **kwargs
568
+ )