MatplotLibAPI 3.2.17__py3-none-any.whl → 3.2.19__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.
MatplotLibAPI/Area.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Area chart helpers."""
2
2
 
3
- from typing import Any, Optional, Tuple
3
+ from typing import Any, Dict, Optional, Tuple
4
4
 
5
5
  import pandas as pd
6
6
  from matplotlib.axes import Axes
@@ -61,6 +61,8 @@ def fplot_area(
61
61
  title: Optional[str] = None,
62
62
  style: StyleTemplate = AREA_STYLE_TEMPLATE,
63
63
  figsize: Tuple[float, float] = (10, 6),
64
+ save_path: Optional[str] = None,
65
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
64
66
  ) -> Figure:
65
67
  """Plot area charts on a new figure."""
66
68
  return _wrap_aplot(
@@ -73,4 +75,6 @@ def fplot_area(
73
75
  stacked=stacked,
74
76
  title=title,
75
77
  style=style,
78
+ save_path=save_path,
79
+ savefig_kwargs=savefig_kwargs,
76
80
  )
MatplotLibAPI/Bar.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Bar and stacked bar chart helpers."""
2
2
 
3
- from typing import Any, Optional, Tuple
3
+ from typing import Any, Dict, Optional, Tuple
4
4
 
5
5
  import pandas as pd
6
6
  import seaborn as sns
@@ -64,6 +64,8 @@ def fplot_bar(
64
64
  title: Optional[str] = None,
65
65
  style: StyleTemplate = DISTRIBUTION_STYLE_TEMPLATE,
66
66
  figsize: Tuple[float, float] = (10, 6),
67
+ save_path: Optional[str] = None,
68
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
67
69
  ) -> Figure:
68
70
  """Plot bar or stacked bar charts on a new figure."""
69
71
  return _wrap_aplot(
@@ -76,4 +78,6 @@ def fplot_bar(
76
78
  stacked=stacked,
77
79
  title=title,
78
80
  style=style,
81
+ save_path=save_path,
82
+ savefig_kwargs=savefig_kwargs,
79
83
  )
@@ -1,6 +1,6 @@
1
1
  """Box and violin plot helpers."""
2
2
 
3
- from typing import Any, Optional, Tuple
3
+ from typing import Any, Dict, Optional, Tuple
4
4
 
5
5
  import pandas as pd
6
6
  import seaborn as sns
@@ -55,6 +55,8 @@ def fplot_box_violin(
55
55
  title: Optional[str] = None,
56
56
  style: StyleTemplate = DISTRIBUTION_STYLE_TEMPLATE,
57
57
  figsize: Tuple[float, float] = (10, 6),
58
+ save_path: Optional[str] = None,
59
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
58
60
  ) -> Figure:
59
61
  """Plot box or violin charts on a new figure."""
60
62
  return _wrap_aplot(
@@ -66,4 +68,6 @@ def fplot_box_violin(
66
68
  violin=violin,
67
69
  title=title,
68
70
  style=style,
71
+ save_path=save_path,
72
+ savefig_kwargs=savefig_kwargs,
69
73
  )
MatplotLibAPI/Bubble.py CHANGED
@@ -4,7 +4,7 @@ Provides functions to create and render bubble charts using seaborn and matplotl
4
4
  with customizable styling via `StyleTemplate`.
5
5
  """
6
6
 
7
- from typing import Dict, Optional, Tuple, cast
7
+ from typing import Any, Dict, Optional, Tuple, cast
8
8
 
9
9
  import matplotlib.pyplot as plt
10
10
  import pandas as pd
@@ -374,6 +374,8 @@ def fplot_bubble(
374
374
  hline: bool = False,
375
375
  vline: bool = False,
376
376
  figsize: Tuple[float, float] = (19.2, 10.8),
377
+ save_path: Optional[str] = None,
378
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
377
379
  ) -> Figure:
378
380
  """Create a new matplotlib Figure with a bubble chart.
379
381
 
@@ -450,4 +452,6 @@ def fplot_bubble(
450
452
  vline=vline,
451
453
  ax=ax,
452
454
  )
455
+ if save_path:
456
+ fig.savefig(save_path, **(savefig_kwargs or {}))
453
457
  return fig
MatplotLibAPI/Heatmap.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Heatmap and correlation matrix helpers."""
2
2
 
3
- from typing import Any, Optional, Sequence, Tuple
3
+ from typing import Any, Dict, Optional, Sequence, Tuple
4
4
 
5
5
  import numpy as np
6
6
  import pandas as pd
@@ -79,6 +79,8 @@ def fplot_heatmap(
79
79
  title: Optional[str] = None,
80
80
  style: StyleTemplate = HEATMAP_STYLE_TEMPLATE,
81
81
  figsize: Tuple[float, float] = (10, 6),
82
+ save_path: Optional[str] = None,
83
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
82
84
  ) -> Figure:
83
85
  """Plot a matrix heatmap on a new figure."""
84
86
  return _wrap_aplot(
@@ -90,6 +92,8 @@ def fplot_heatmap(
90
92
  value=value,
91
93
  title=title,
92
94
  style=style,
95
+ save_path=save_path,
96
+ savefig_kwargs=savefig_kwargs,
93
97
  )
94
98
 
95
99
 
@@ -100,6 +104,8 @@ def fplot_correlation_matrix(
100
104
  title: Optional[str] = None,
101
105
  style: StyleTemplate = HEATMAP_STYLE_TEMPLATE,
102
106
  figsize: Tuple[float, float] = (10, 6),
107
+ save_path: Optional[str] = None,
108
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
103
109
  ) -> Figure:
104
110
  """Plot a correlation matrix heatmap on a new figure."""
105
111
  return _wrap_aplot(
@@ -110,4 +116,6 @@ def fplot_correlation_matrix(
110
116
  method=method,
111
117
  title=title,
112
118
  style=style,
119
+ save_path=save_path,
120
+ savefig_kwargs=savefig_kwargs,
113
121
  )
@@ -1,6 +1,6 @@
1
1
  """Histogram and KDE plotting helpers."""
2
2
 
3
- from typing import Any, Optional, Tuple
3
+ from typing import Any, Dict, Optional, Tuple
4
4
 
5
5
  import pandas as pd
6
6
  import seaborn as sns
@@ -55,6 +55,8 @@ def fplot_histogram_kde(
55
55
  title: Optional[str] = None,
56
56
  style: StyleTemplate = DISTRIBUTION_STYLE_TEMPLATE,
57
57
  figsize: Tuple[float, float] = (10, 6),
58
+ save_path: Optional[str] = None,
59
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
58
60
  ) -> Figure:
59
61
  """Plot a histogram with optional KDE on a new figure."""
60
62
  return _wrap_aplot(
@@ -66,4 +68,6 @@ def fplot_histogram_kde(
66
68
  kde=kde,
67
69
  title=title,
68
70
  style=style,
71
+ save_path=save_path,
72
+ savefig_kwargs=savefig_kwargs,
69
73
  )
MatplotLibAPI/Network.py CHANGED
@@ -807,6 +807,8 @@ def fplot_network(
807
807
  ascending: bool = False,
808
808
  node_list: Optional[List] = None,
809
809
  figsize: Tuple[float, float] = (19.2, 10.8),
810
+ save_path: Optional[str] = None,
811
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
810
812
  ) -> Figure:
811
813
  """Return a figure with a network graph.
812
814
 
@@ -853,6 +855,8 @@ def fplot_network(
853
855
  node_list=node_list,
854
856
  ax=ax,
855
857
  )
858
+ if save_path:
859
+ fig.savefig(save_path, **(savefig_kwargs or {}))
856
860
  return fig
857
861
 
858
862
 
@@ -868,6 +872,8 @@ def fplot_network_components(
868
872
  node_list: Optional[List] = None,
869
873
  figsize: Tuple[float, float] = (19.2, 10.8),
870
874
  n_cols: Optional[int] = None,
875
+ save_path: Optional[str] = None,
876
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
871
877
  ) -> Figure:
872
878
  """Return a figure showing individual network components.
873
879
 
@@ -945,4 +951,6 @@ def fplot_network_components(
945
951
 
946
952
  plt.tight_layout(rect=(0, 0.03, 1, 0.95))
947
953
 
954
+ if save_path:
955
+ fig.savefig(save_path, **(savefig_kwargs or {}))
948
956
  return fig
MatplotLibAPI/Pie.py CHANGED
@@ -52,6 +52,8 @@ def fplot_pie_donut(
52
52
  title: Optional[str] = None,
53
53
  style: StyleTemplate = PIE_STYLE_TEMPLATE,
54
54
  figsize: Tuple[float, float] = (8, 8),
55
+ save_path: Optional[str] = None,
56
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
55
57
  ) -> Figure:
56
58
  """Plot pie or donut charts on a new figure."""
57
59
  return _wrap_aplot(
@@ -63,4 +65,6 @@ def fplot_pie_donut(
63
65
  donut=donut,
64
66
  title=title,
65
67
  style=style,
68
+ save_path=save_path,
69
+ savefig_kwargs=savefig_kwargs,
66
70
  )
MatplotLibAPI/Sankey.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Sankey plotting helpers."""
2
2
 
3
- from typing import Dict, List, Optional
3
+ from typing import Any, Dict, List, Optional
4
4
 
5
5
  import pandas as pd
6
6
  import plotly.graph_objects as go
@@ -15,6 +15,8 @@ def fplot_sankey(
15
15
  value: str,
16
16
  title: Optional[str] = None,
17
17
  style: StyleTemplate = SANKEY_STYLE_TEMPLATE,
18
+ save_path: Optional[str] = None,
19
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
18
20
  ) -> go.Figure:
19
21
  """Plot a Sankey diagram showing flows between categories."""
20
22
  validate_dataframe(pd_df, cols=[source, target, value])
@@ -36,4 +38,9 @@ def fplot_sankey(
36
38
  fig.update_layout(
37
39
  title_text=title, font=dict(color=style.font_color, size=style.font_size)
38
40
  )
41
+ if save_path:
42
+ if save_path.lower().endswith((".html", ".htm")):
43
+ fig.write_html(save_path, **(savefig_kwargs or {}))
44
+ else:
45
+ fig.write_image(save_path, **(savefig_kwargs or {}))
39
46
  return fig
MatplotLibAPI/Sunburst.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Sunburst chart plotting utilities."""
2
2
 
3
- from typing import Optional
3
+ from typing import Any, Dict, Optional
4
4
 
5
5
  import pandas as pd
6
6
  import plotly.graph_objects as go
@@ -23,6 +23,8 @@ def fplot_sunburst(
23
23
  ascending: bool = False,
24
24
  max_values: int = 100,
25
25
  fig: Optional[go.Figure] = None,
26
+ save_path: Optional[str] = None,
27
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
26
28
  ) -> go.Figure:
27
29
  """Return a figure containing the sunburst plot.
28
30
 
@@ -79,5 +81,9 @@ def fplot_sunburst(
79
81
  font=dict(family=style.font_name, size=style.font_size, color=style.font_color),
80
82
  showlegend=style.legend if style else True,
81
83
  )
82
-
84
+ if save_path:
85
+ if save_path.lower().endswith((".html", ".htm")):
86
+ fig.write_html(save_path, **(savefig_kwargs or {}))
87
+ else:
88
+ fig.write_image(save_path, **(savefig_kwargs or {}))
83
89
  return fig
MatplotLibAPI/Table.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Table plotting helpers."""
2
2
 
3
- from typing import List, Optional, Tuple, cast
3
+ from typing import Any, Dict, List, Optional, Tuple, cast
4
4
  import pandas as pd
5
5
  import matplotlib.pyplot as plt
6
6
  from matplotlib.axes import Axes
@@ -173,6 +173,8 @@ def fplot_table(
173
173
  sort_by: Optional[str] = None,
174
174
  ascending: bool = False,
175
175
  figsize: Tuple[float, float] = (19.2, 10.8),
176
+ save_path: Optional[str] = None,
177
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
176
178
  ) -> Figure:
177
179
  """Return a new figure containing a formatted table.
178
180
 
@@ -217,4 +219,6 @@ def fplot_table(
217
219
  fig.patch.set_facecolor(style.background_color)
218
220
  ax = fig.add_subplot()
219
221
  ax = aplot_table(pd_df, cols, title, style, max_values, sort_by, ascending, ax)
222
+ if save_path:
223
+ fig.savefig(save_path, **(savefig_kwargs or {}))
220
224
  return fig
@@ -1,6 +1,6 @@
1
1
  """Timeserie plotting helpers."""
2
2
 
3
- from typing import Dict, Optional, Tuple, cast
3
+ from typing import Any, Dict, Optional, Tuple, cast
4
4
 
5
5
  import matplotlib.pyplot as plt
6
6
  import pandas as pd
@@ -270,6 +270,8 @@ def fplot_timeserie(
270
270
  ascending: bool = False,
271
271
  std: bool = False,
272
272
  figsize: Tuple[float, float] = (19.2, 10.8),
273
+ save_path: Optional[str] = None,
274
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
273
275
  ) -> Figure:
274
276
  """Return a figure plotting the time series.
275
277
 
@@ -336,6 +338,8 @@ def fplot_timeserie(
336
338
  ascending=ascending,
337
339
  ax=ax,
338
340
  )
341
+ if save_path:
342
+ fig.savefig(save_path, **(savefig_kwargs or {}))
339
343
  return fig
340
344
 
341
345
 
MatplotLibAPI/Treemap.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Treemap plotting utilities."""
2
2
 
3
- from typing import Optional
3
+ from typing import Any, Dict, Optional
4
4
 
5
5
  import pandas as pd
6
6
  import plotly.graph_objects as go
@@ -103,6 +103,8 @@ def fplot_treemap(
103
103
  ascending: bool = False,
104
104
  max_values: int = 100,
105
105
  fig: Optional[go.Figure] = None,
106
+ save_path: Optional[str] = None,
107
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
106
108
  ) -> go.Figure:
107
109
  """Return a figure containing the treemap plot.
108
110
 
@@ -162,4 +164,9 @@ def fplot_treemap(
162
164
  # Apply color scale
163
165
  fig.update_traces(marker=dict(colorscale=style.palette))
164
166
 
167
+ if save_path:
168
+ if save_path.lower().endswith((".html", ".htm")):
169
+ fig.write_html(save_path, **(savefig_kwargs or {}))
170
+ else:
171
+ fig.write_image(save_path, **(savefig_kwargs or {}))
165
172
  return fig
MatplotLibAPI/Waffle.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Waffle chart helpers."""
2
2
 
3
- from typing import Any, Optional, Tuple
3
+ from typing import Any, Dict, Optional, Tuple
4
4
 
5
5
  import pandas as pd
6
6
  import seaborn as sns
@@ -68,6 +68,8 @@ def fplot_waffle(
68
68
  title: Optional[str] = None,
69
69
  style: StyleTemplate = PIE_STYLE_TEMPLATE,
70
70
  figsize: Tuple[float, float] = (8, 8),
71
+ save_path: Optional[str] = None,
72
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
71
73
  ) -> Figure:
72
74
  """Plot waffle charts on a new figure."""
73
75
  return _wrap_aplot(
@@ -79,4 +81,6 @@ def fplot_waffle(
79
81
  rows=rows,
80
82
  title=title,
81
83
  style=style,
84
+ save_path=save_path,
85
+ savefig_kwargs=savefig_kwargs,
82
86
  )
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Iterable, Optional, Sequence, Tuple, cast
5
+ from typing import Any, Dict, Iterable, Optional, Sequence, Tuple, cast
6
6
 
7
7
  import numpy as np
8
8
  import pandas as pd
@@ -131,6 +131,40 @@ def _prepare_word_frequencies(
131
131
  return words, weights
132
132
 
133
133
 
134
+ def create_circular_mask(size: int = 300, radius: Optional[int] = None) -> np.ndarray:
135
+ """Construct a binary mask with a circular opening for a word cloud.
136
+
137
+ Parameters
138
+ ----------
139
+ size : int, optional
140
+ Width and height of the mask in pixels. Defaults to ``300``.
141
+ radius : int, optional
142
+ Radius of the circular opening in pixels. Defaults to ``size // 2``.
143
+
144
+ Returns
145
+ -------
146
+ numpy.ndarray
147
+ Two-dimensional array suitable for the ``mask`` argument of
148
+ ``wordcloud.WordCloud`` where ``0`` values define the drawable region.
149
+
150
+ Raises
151
+ ------
152
+ ValueError
153
+ If ``size`` or ``radius`` are non-positive.
154
+ """
155
+ if size <= 0:
156
+ raise ValueError("size must be a positive integer.")
157
+
158
+ resolved_radius = radius if radius is not None else size // 2
159
+ if resolved_radius <= 0:
160
+ raise ValueError("radius must be a positive integer.")
161
+
162
+ center = (size - 1) / 2
163
+ x, y = np.ogrid[:size, :size]
164
+ mask_region = (x - center) ** 2 + (y - center) ** 2 > resolved_radius**2
165
+ return 255 * mask_region.astype(np.uint8)
166
+
167
+
134
168
  def _plot_words(
135
169
  ax: Axes,
136
170
  words: Sequence[str],
@@ -138,6 +172,7 @@ def _plot_words(
138
172
  style: StyleTemplate,
139
173
  title: Optional[str],
140
174
  random_state: Optional[int],
175
+ mask: Optional[np.ndarray],
141
176
  ) -> Axes:
142
177
  """Render words on the provided axes with sizes proportional to weights.
143
178
 
@@ -179,8 +214,20 @@ def _plot_words(
179
214
 
180
215
  canvas.draw()
181
216
  ax_bbox = ax.get_window_extent()
182
- width = max(int(ax_bbox.width), 1)
183
- height = max(int(ax_bbox.height), 1)
217
+ resolved_mask = create_circular_mask() if mask is None else np.asarray(mask)
218
+ if resolved_mask is not None and resolved_mask.ndim != 2:
219
+ raise ValueError("mask must be a 2D array.")
220
+
221
+ width = (
222
+ max(int(ax_bbox.width), 1)
223
+ if resolved_mask is None
224
+ else max(int(resolved_mask.shape[1]), 1)
225
+ )
226
+ height = (
227
+ max(int(ax_bbox.height), 1)
228
+ if resolved_mask is None
229
+ else max(int(resolved_mask.shape[0]), 1)
230
+ )
184
231
 
185
232
  frequency_map = {
186
233
  string_formatter(word): weight for word, weight in zip(words, weights)
@@ -195,6 +242,7 @@ def _plot_words(
195
242
  min_font_size=int(font_sizes.min(initial=style.font_size)),
196
243
  max_font_size=int(font_sizes.max(initial=style.font_size * 4)),
197
244
  random_state=random_state,
245
+ mask=resolved_mask,
198
246
  ).generate_from_frequencies(frequency_map)
199
247
 
200
248
  ax.imshow(wc, interpolation="bilinear")
@@ -214,6 +262,7 @@ def aplot_wordcloud(
214
262
  stopwords: Optional[Iterable[str]] = None,
215
263
  random_state: Optional[int] = None,
216
264
  ax: Optional[Axes] = None,
265
+ mask: Optional[np.ndarray] = None,
217
266
  ) -> Axes:
218
267
  """Plot a word cloud on the provided axes.
219
268
 
@@ -237,6 +286,9 @@ def aplot_wordcloud(
237
286
  Seed for word placement. Defaults to ``None``.
238
287
  ax : matplotlib.axes.Axes, optional
239
288
  Axes to draw on. Defaults to ``None`` which uses the current axes.
289
+ mask : numpy.ndarray, optional
290
+ Two-dimensional mask array defining the drawable region of the word cloud.
291
+ Defaults to a circular mask generated by :func:`create_circular_mask`.
240
292
 
241
293
  Returns
242
294
  -------
@@ -259,7 +311,13 @@ def aplot_wordcloud(
259
311
  stopwords=stopwords,
260
312
  )
261
313
  return _plot_words(
262
- ax, words, weights, style=style, title=title, random_state=random_state
314
+ ax,
315
+ words,
316
+ weights,
317
+ style=style,
318
+ title=title,
319
+ random_state=random_state,
320
+ mask=mask,
263
321
  )
264
322
 
265
323
 
@@ -273,6 +331,9 @@ def fplot_wordcloud(
273
331
  stopwords: Optional[Iterable[str]] = None,
274
332
  random_state: Optional[int] = None,
275
333
  figsize: Tuple[float, float] = FIG_SIZE,
334
+ save_path: Optional[str] = None,
335
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
336
+ mask: Optional[np.ndarray] = None,
276
337
  ) -> Figure:
277
338
  """Create a new figure with a word cloud.
278
339
 
@@ -296,6 +357,9 @@ def fplot_wordcloud(
296
357
  Seed for word placement. Defaults to ``None``.
297
358
  figsize : tuple of float, optional
298
359
  Figure size. Defaults to ``FIG_SIZE``.
360
+ mask : numpy.ndarray, optional
361
+ Two-dimensional mask array defining the drawable region of the word cloud.
362
+ Defaults to a circular mask generated by :func:`create_circular_mask`.
299
363
 
300
364
  Returns
301
365
  -------
@@ -323,7 +387,10 @@ def fplot_wordcloud(
323
387
  style=style,
324
388
  title=title,
325
389
  random_state=random_state,
390
+ mask=mask,
326
391
  )
327
392
  fig.patch.set_facecolor(style.background_color)
328
393
  fig.tight_layout()
394
+ if save_path:
395
+ fig.savefig(save_path, **(savefig_kwargs or {}))
329
396
  return fig
MatplotLibAPI/__init__.py CHANGED
@@ -35,7 +35,12 @@ from .Timeserie import TIMESERIE_STYLE_TEMPLATE, aplot_timeserie, fplot_timeseri
35
35
  from .Sunburst import fplot_sunburst
36
36
  from .Treemap import TREEMAP_STYLE_TEMPLATE, fplot_treemap
37
37
  from .Waffle import aplot_waffle, fplot_waffle
38
- from .Wordcloud import WORDCLOUD_STYLE_TEMPLATE, aplot_wordcloud, fplot_wordcloud
38
+ from .Wordcloud import (
39
+ WORDCLOUD_STYLE_TEMPLATE,
40
+ aplot_wordcloud,
41
+ create_circular_mask,
42
+ fplot_wordcloud,
43
+ )
39
44
  from .accessor import DataFrameAccessor
40
45
 
41
46
  __all__ = [
@@ -54,6 +59,7 @@ __all__ = [
54
59
  "aplot_correlation_matrix",
55
60
  "aplot_area",
56
61
  "aplot_pie_donut",
62
+ "create_circular_mask",
57
63
  "aplot_waffle",
58
64
  "fplot_bubble",
59
65
  "fplot_network",
@@ -23,9 +23,37 @@ def _wrap_aplot(
23
23
  pd_df: Any,
24
24
  figsize: Tuple[float, float],
25
25
  ax_args: Optional[Dict[str, Any]] = None,
26
+ save_path: Optional[str] = None,
27
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
26
28
  **kwargs: Any,
27
29
  ) -> Figure:
28
- """Create a new figure and delegate plotting to an axis-level function."""
30
+ """Create a new figure and delegate plotting to an axis-level function.
31
+
32
+ Parameters
33
+ ----------
34
+ plot_func : _AplotFunc
35
+ Axis-level plotting callable.
36
+ pd_df : Any
37
+ Data passed to the plotting function.
38
+ figsize : tuple[float, float]
39
+ Size of the created figure.
40
+ ax_args : dict, optional
41
+ Additional keyword arguments forwarded to ``plt.subplots``.
42
+ save_path : str, optional
43
+ File path where the figure should be saved. The default is ``None``
44
+ and no file is written.
45
+ savefig_kwargs : dict, optional
46
+ Extra keyword arguments forwarded to ``Figure.savefig`` when
47
+ ``save_path`` is provided. Defaults to ``None``.
48
+ **kwargs : Any
49
+ Additional arguments forwarded to ``plot_func``.
50
+
51
+ Returns
52
+ -------
53
+ Figure
54
+ Figure containing the rendered plot. If ``save_path`` is supplied the
55
+ figure is saved before being returned.
56
+ """
29
57
  ax_args = ax_args or {}
30
58
  fig, axes_obj = plt.subplots(figsize=figsize, **ax_args)
31
59
  ax: Axes
@@ -35,4 +63,6 @@ def _wrap_aplot(
35
63
  ax = cast(Axes, axes_obj.flat[0] if isinstance(axes_obj, ndarray) else axes_obj)
36
64
  plot_func(pd_df=pd_df, ax=ax, **kwargs)
37
65
  fig_obj: Figure = cast(Figure, fig)
66
+ if save_path:
67
+ fig_obj.savefig(save_path, **(savefig_kwargs or {}))
38
68
  return fig_obj
MatplotLibAPI/accessor.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Pandas accessor exposing MatplotLibAPI plotting helpers."""
2
2
 
3
- from typing import Dict, List, Optional, Tuple
3
+ from typing import Any, Dict, List, Optional, Tuple
4
4
 
5
5
  import numpy as np
6
6
  import pandas as pd
@@ -211,6 +211,8 @@ class DataFrameAccessor:
211
211
  hline: bool = False,
212
212
  vline: bool = False,
213
213
  figsize: Tuple[float, float] = (19.2, 10.8),
214
+ save_path: Optional[str] = None,
215
+ savefig_kwargs: Optional[Dict[str, Any]] = None,
214
216
  ) -> Figure:
215
217
  """Plot a bubble chart on a new figure.
216
218
 
@@ -263,6 +265,8 @@ class DataFrameAccessor:
263
265
  hline=hline,
264
266
  vline=vline,
265
267
  figsize=figsize,
268
+ save_path=save_path,
269
+ savefig_kwargs=savefig_kwargs,
266
270
  )
267
271
 
268
272
  def fplot_composite_bubble(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: MatplotLibAPI
3
- Version: 3.2.17
3
+ Version: 3.2.19
4
4
  License-File: LICENSE
5
5
  Requires-Python: >=3.8
6
6
  Requires-Dist: kaleido
@@ -0,0 +1,26 @@
1
+ MatplotLibAPI/Area.py,sha256=Y-tk6Di3Foj3yOGVbbOwDnPtL9rDh-VV2XTeaZcybgk,2095
2
+ MatplotLibAPI/Bar.py,sha256=Y8mP_UWyU2h5T38L7j-Vnt0t9WSeCbV6Gw_-_48x3Bw,2243
3
+ MatplotLibAPI/BoxViolin.py,sha256=zsyfUKYp6wKD30i-LWmwPxtOA7ljjh874xxES_GHZ8M,1947
4
+ MatplotLibAPI/Bubble.py,sha256=xByA6J89L1ye8oiinGQx1jd4PC0vPcBQhxFrKCEXtVM,12814
5
+ MatplotLibAPI/Composite.py,sha256=k4elPk2mucw5oOH2S2GZV6mbHI9N4Nhpnte4mWLHObg,5902
6
+ MatplotLibAPI/Heatmap.py,sha256=SRT8pCKtEaJ1PivxxzCuXp-OBu4ljno2PGB_XXvFxzY,3369
7
+ MatplotLibAPI/Histogram.py,sha256=znkQAVOa2-DMIKopCl_3-8JpDtymfGm4Bi4IyNXSVqs,1869
8
+ MatplotLibAPI/Network.py,sha256=oxDPmhKWjkwGonL6xTDo_f-O5jKTrAGbvyV0kb4uUOI,30472
9
+ MatplotLibAPI/Pie.py,sha256=p0JuSP8h3TflEuvmGpPqNHO7hbAnse8hmMWBiZtzfsE,1882
10
+ MatplotLibAPI/Pivot.py,sha256=6qH8e6U1TzUQcAIBmA_KMuHER2Uxp0-GFtwy9eJuS9A,3403
11
+ MatplotLibAPI/Sankey.py,sha256=SpijCISghlsLqPuaWvnBP6vB-CV9k7FUGUi5LC6bKVc,1501
12
+ MatplotLibAPI/StyleTemplate.py,sha256=Y3sBbUMbfAuxaONW8YixaI0UGgC7b1xnUo0MUMV4Z98,8176
13
+ MatplotLibAPI/Sunburst.py,sha256=kqjEruXDDeuJpUKqbMw_VdT7fY0O4qzUNsIuwaTamdc,2584
14
+ MatplotLibAPI/Table.py,sha256=jRdnQ0LNA5op65QJhXnXv_v7tBv1JEPLX7qHNd07_is,6448
15
+ MatplotLibAPI/Timeserie.py,sha256=vN8Ed9eC6TcN02LAiSJRzbIW3ZNoBo8ip7lznnK5eG0,10198
16
+ MatplotLibAPI/Treemap.py,sha256=VBBk6MpNXoQtnxFzR1YPhIx6Lz9b7yJNHBMbQDhvefM,4848
17
+ MatplotLibAPI/Waffle.py,sha256=uplRhUBDWUhSwPnI_GzU1O2D_RQXW_0OJ51m01PFKLg,2517
18
+ MatplotLibAPI/Wordcloud.py,sha256=lxBeB61dPbjc2WulZawCiCmjf_s7KiPib1zW70V9nH8,12123
19
+ MatplotLibAPI/__init__.py,sha256=jyMVtJq3rGJ9GmM7mX1dhJcNCCJHJ2-IwtDClRgKBFg,2304
20
+ MatplotLibAPI/_typing.py,sha256=Or3IPNceWKdyEk3CGXJb09FZR_fvT732oF0iWrx1ex8,598
21
+ MatplotLibAPI/_visualization_utils.py,sha256=qIv7c0Mi3qK-saGxmKngw23uWxKFSAYjiH3uYTSr5Po,2215
22
+ MatplotLibAPI/accessor.py,sha256=Wsje4q6bNa_-WAkljqTDWfbWpKcbAy2JKaHir9qZ9Ho,53038
23
+ matplotlibapi-3.2.19.dist-info/METADATA,sha256=0VPbE_llP391GgQWHC2DK99Gkl5E1xZQzPcPxC1WjEM,5888
24
+ matplotlibapi-3.2.19.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
25
+ matplotlibapi-3.2.19.dist-info/licenses/LICENSE,sha256=hMErKLb6YZR3lRR5zr-vxeFkvY69QAaafgSpZ5-P1dQ,1067
26
+ matplotlibapi-3.2.19.dist-info/RECORD,,
@@ -1,26 +0,0 @@
1
- MatplotLibAPI/Area.py,sha256=cGStEYunusfJdkKOF4199l5LH-ZV-xk8Pe8RAeBaPt8,1931
2
- MatplotLibAPI/Bar.py,sha256=WY74gXJA3ZIpJD0WaidMo0lrT1lVEbeA0UMGFBY5yiE,2079
3
- MatplotLibAPI/BoxViolin.py,sha256=XB4cUxUvf8LzwE2twu0gd7vn2NJYjz_mQwVqtyE7dYU,1783
4
- MatplotLibAPI/Bubble.py,sha256=PiK6Fe77mXRTSSewXkimrNFsMa32pGRXr9jlgZJndXA,12644
5
- MatplotLibAPI/Composite.py,sha256=k4elPk2mucw5oOH2S2GZV6mbHI9N4Nhpnte4mWLHObg,5902
6
- MatplotLibAPI/Heatmap.py,sha256=Qs17CHGhBDXUVDxW0dofzjO5xxlQw5XIwANtUKHgg_Y,3047
7
- MatplotLibAPI/Histogram.py,sha256=0J4uC7xy53TZKjTDWCeEjaELL7E5lQDG0MpeGfaaO6Y,1705
8
- MatplotLibAPI/Network.py,sha256=erjKzl1Jb6j6Fiy3170xKSeF1LEBe7jPdLB6q8VZclw,30142
9
- MatplotLibAPI/Pie.py,sha256=TBAnj4mVYy6dKPMwXPjGanTDrLrjHmA5pFvrdXbNw9A,1724
10
- MatplotLibAPI/Pivot.py,sha256=6qH8e6U1TzUQcAIBmA_KMuHER2Uxp0-GFtwy9eJuS9A,3403
11
- MatplotLibAPI/Sankey.py,sha256=Q_zmEcER8PGPDro6W4R_SEs17ejfi6D0q-kH6mxkFcI,1187
12
- MatplotLibAPI/StyleTemplate.py,sha256=Y3sBbUMbfAuxaONW8YixaI0UGgC7b1xnUo0MUMV4Z98,8176
13
- MatplotLibAPI/Sunburst.py,sha256=ksPV5D40FQcVXQQ1QOHYMc0WMCcjmt9iRrbeH4g85uE,2265
14
- MatplotLibAPI/Table.py,sha256=EBxXJA6GKjFhWcOMwJ6Wfm-UNw3Ha5KBZ2004TYdkKY,6272
15
- MatplotLibAPI/Timeserie.py,sha256=s6u68IlugqPMpJk-X5hr-k1WDZyx97Ov7VKQOztXo_U,10028
16
- MatplotLibAPI/Treemap.py,sha256=a-9Z-ZzXzIV5SDgdJaW7slGELFBBks1pXZnIjcYmarw,4528
17
- MatplotLibAPI/Waffle.py,sha256=gPREV5v92DQcvjNGuwdKDbAaRSzLBbGF8sWPGUwFyJM,2353
18
- MatplotLibAPI/Wordcloud.py,sha256=aQnLQ4AxHaa2-6PE3ThbmjoQF4DN4oYTaRgRur_evRc,9840
19
- MatplotLibAPI/__init__.py,sha256=6Z51NTmLCoM7P-XPDGVQdtcXtz8S1zZzoByuX_nCpyw,2233
20
- MatplotLibAPI/_typing.py,sha256=Or3IPNceWKdyEk3CGXJb09FZR_fvT732oF0iWrx1ex8,598
21
- MatplotLibAPI/_visualization_utils.py,sha256=RQBgS-ytPorEOuWqQMHJRwaKOgmZoMW22-sjzxkui2I,1179
22
- MatplotLibAPI/accessor.py,sha256=jcLrMP30v_G4rMNV1_peM-_cpxk6bIh11snvHGAUUpE,52859
23
- matplotlibapi-3.2.17.dist-info/METADATA,sha256=g6-L4pc_nY0GtaopfPavA5ANDLVyhd7fTJ-McH6VNYo,5888
24
- matplotlibapi-3.2.17.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
25
- matplotlibapi-3.2.17.dist-info/licenses/LICENSE,sha256=hMErKLb6YZR3lRR5zr-vxeFkvY69QAaafgSpZ5-P1dQ,1067
26
- matplotlibapi-3.2.17.dist-info/RECORD,,