MatplotLibAPI 3.1.0__py3-none-any.whl → 3.1.1__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/Bubble.py +4 -4
- MatplotLibAPI/Composite.py +8 -5
- MatplotLibAPI/Network.py +58 -22
- MatplotLibAPI/Pivot.py +6 -5
- MatplotLibAPI/Table.py +4 -2
- MatplotLibAPI/Timeserie.py +6 -4
- MatplotLibAPI/Treemap.py +35 -12
- MatplotLibAPI/__init__.py +297 -10
- {MatplotLibAPI-3.1.0.dist-info → MatplotLibAPI-3.1.1.dist-info}/METADATA +10 -2
- MatplotLibAPI-3.1.1.dist-info/RECORD +13 -0
- MatplotLibAPI/Style.py +0 -171
- MatplotLibAPI/pdAccessor.py +0 -147
- MatplotLibAPI-3.1.0.dist-info/RECORD +0 -15
- {MatplotLibAPI-3.1.0.dist-info → MatplotLibAPI-3.1.1.dist-info}/LICENSE +0 -0
- {MatplotLibAPI-3.1.0.dist-info → MatplotLibAPI-3.1.1.dist-info}/WHEEL +0 -0
- {MatplotLibAPI-3.1.0.dist-info → MatplotLibAPI-3.1.1.dist-info}/top_level.txt +0 -0
MatplotLibAPI/Bubble.py
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# Hint for Visual Code Python Interactive window
|
|
2
2
|
# %%
|
|
3
|
-
|
|
3
|
+
from typing import Optional
|
|
4
4
|
import pandas as pd
|
|
5
5
|
import matplotlib.pyplot as plt
|
|
6
6
|
from matplotlib.axes import Axes
|
|
7
7
|
import seaborn as sns
|
|
8
|
-
from typing import Optional
|
|
9
|
-
from .Style import DynamicFuncFormatter, StyleTemplate, generate_ticks, _validate_panda, string_formatter, bmk_formatter, percent_formatter, format_func
|
|
10
8
|
|
|
9
|
+
from . import DynamicFuncFormatter, StyleTemplate, generate_ticks, string_formatter, bmk_formatter, percent_formatter, format_func
|
|
10
|
+
from .. import validate_dataframe
|
|
11
11
|
|
|
12
12
|
BUBBLE_STYLE_TEMPLATE = StyleTemplate(
|
|
13
13
|
format_funcs={"label": string_formatter,
|
|
@@ -33,7 +33,7 @@ def plot_bubble(
|
|
|
33
33
|
ascending: bool = False,
|
|
34
34
|
ax: Optional[Axes] = None):
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
validate_dataframe(pd_df, cols=[label, x, y, z], sort_by=sort_by)
|
|
37
37
|
style.format_funcs = format_func(
|
|
38
38
|
style.format_funcs, label=label, x=x, y=y, z=z)
|
|
39
39
|
if not sort_by:
|
MatplotLibAPI/Composite.py
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# Hint for Visual Code Python Interactive window
|
|
2
2
|
# %%
|
|
3
|
+
from typing import Optional, Tuple
|
|
4
|
+
import pandas as pd
|
|
3
5
|
import matplotlib.pyplot as plt
|
|
4
6
|
from matplotlib.figure import Figure
|
|
5
|
-
|
|
7
|
+
|
|
8
|
+
from .Network import plot_network, plot_network_components, DEFAULT
|
|
6
9
|
from .Bubble import plot_bubble, BUBBLE_STYLE_TEMPLATE
|
|
7
10
|
from .Table import plot_table
|
|
8
|
-
from
|
|
9
|
-
from
|
|
11
|
+
from . import StyleTemplate, format_func
|
|
12
|
+
from .. import validate_dataframe
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
def plot_composite_bubble(
|
|
@@ -19,13 +22,13 @@ def plot_composite_bubble(
|
|
|
19
22
|
style: StyleTemplate = BUBBLE_STYLE_TEMPLATE,
|
|
20
23
|
max_values: int = 50,
|
|
21
24
|
center_to_mean: bool = False,
|
|
22
|
-
filter_by:Optional[str] = None,
|
|
25
|
+
filter_by: Optional[str] = None,
|
|
23
26
|
sort_by: Optional[str] = None,
|
|
24
27
|
ascending: bool = False,
|
|
25
28
|
table_rows: int = 10,
|
|
26
29
|
figsize: Tuple[float, float] = (19.2, 10.8)) -> Figure:
|
|
27
30
|
|
|
28
|
-
|
|
31
|
+
validate_dataframe(pd_df, cols=[label, x, y, z], sort_by=sort_by)
|
|
29
32
|
|
|
30
33
|
if not sort_by:
|
|
31
34
|
sort_by = z
|
MatplotLibAPI/Network.py
CHANGED
|
@@ -13,7 +13,8 @@ from networkx import Graph
|
|
|
13
13
|
from networkx.classes.graph import Graph
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
from .
|
|
16
|
+
from . import StyleTemplate, string_formatter, format_func
|
|
17
|
+
from .. import validate_dataframe
|
|
17
18
|
|
|
18
19
|
NETWORK_STYLE_TEMPLATE = StyleTemplate(
|
|
19
20
|
)
|
|
@@ -165,23 +166,22 @@ class Graph(nx.Graph):
|
|
|
165
166
|
|
|
166
167
|
return node_size, edges_width, fonts_size
|
|
167
168
|
|
|
168
|
-
def
|
|
169
|
+
def subgraph(self, node_list=None, max_edges: int = DEFAULT["MAX_EDGES"]) -> Graph:
|
|
169
170
|
if node_list is None:
|
|
170
171
|
node_list = self.nodes.sort("weight")[:DEFAULT["MAX_NODES"]]
|
|
171
172
|
connected_subgraph_nodes = list(self.find_connected_subgraph())
|
|
172
173
|
node_list = [
|
|
173
174
|
node for node in node_list if node in connected_subgraph_nodes]
|
|
174
175
|
|
|
175
|
-
subgraph = nx.subgraph(
|
|
176
|
-
self, nbunch=node_list)
|
|
176
|
+
subgraph = nx.subgraph(self, nbunch=node_list)
|
|
177
177
|
edges = subgraph.top_k_edges(attribute="weight", k=5).keys()
|
|
178
178
|
subgraph = subgraph.edge_subgraph(list(edges)[:max_edges])
|
|
179
|
-
return subgraph
|
|
179
|
+
return Graph(subgraph)
|
|
180
180
|
|
|
181
|
-
def
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
181
|
+
def plot_network(self,
|
|
182
|
+
title: str = "Test",
|
|
183
|
+
style: StyleTemplate = NETWORK_STYLE_TEMPLATE,
|
|
184
|
+
ax: Optional[Axes] = None) -> Axes:
|
|
185
185
|
"""
|
|
186
186
|
Plots the degree distribution of the graph, including a degree rank plot and a degree histogram.
|
|
187
187
|
"""
|
|
@@ -227,7 +227,7 @@ class Graph(nx.Graph):
|
|
|
227
227
|
|
|
228
228
|
return ax
|
|
229
229
|
|
|
230
|
-
def
|
|
230
|
+
def plot_network_components(self, node_list: Optional[List] = None,
|
|
231
231
|
scale: int = DEFAULT["GRAPH_SCALE"],
|
|
232
232
|
node_scale: int = DEFAULT["MAX_NODE_SIZE"],
|
|
233
233
|
edge_scale: float = DEFAULT["MAX_EDGE_WIDTH"],
|
|
@@ -235,13 +235,16 @@ class Graph(nx.Graph):
|
|
|
235
235
|
max_edges: int = DEFAULT["MAX_EDGES"],
|
|
236
236
|
plt_title: Optional[str] = "Top keywords"):
|
|
237
237
|
# node_list=self.nodes_circuits(node_list)
|
|
238
|
-
g = self.
|
|
238
|
+
g = self.subgraph(max_edges=max_edges, node_list=node_list)
|
|
239
239
|
connected_components = nx.connected_components(g)
|
|
240
|
+
axes=[]
|
|
240
241
|
for connected_component in connected_components:
|
|
241
242
|
if len(connected_component) > 5:
|
|
242
|
-
connected_component_graph = self.
|
|
243
|
-
|
|
244
|
-
connected_component_graph.
|
|
243
|
+
connected_component_graph = self.subgraph(max_edges=max_edges,
|
|
244
|
+
node_list=connected_component)
|
|
245
|
+
ax=connected_component_graph.plot_network()
|
|
246
|
+
axes.append(ax)
|
|
247
|
+
return axes
|
|
245
248
|
|
|
246
249
|
def find_connected_subgraph(self):
|
|
247
250
|
logging.info(f'find_connected_subgraph')
|
|
@@ -295,7 +298,7 @@ class Graph(nx.Graph):
|
|
|
295
298
|
def from_pandas_edgelist(df: pd.DataFrame,
|
|
296
299
|
source: str = "source",
|
|
297
300
|
target: str = "target",
|
|
298
|
-
weight: str = "weight"):
|
|
301
|
+
weight: str = "weight") -> Graph:
|
|
299
302
|
"""
|
|
300
303
|
Initialize netX instance with a simple dataframe
|
|
301
304
|
|
|
@@ -305,7 +308,6 @@ class Graph(nx.Graph):
|
|
|
305
308
|
:param weight: Name of edges weight column in df_source.
|
|
306
309
|
|
|
307
310
|
"""
|
|
308
|
-
G = Graph()
|
|
309
311
|
G = nx.from_pandas_edgelist(
|
|
310
312
|
df, source=source, target=target, edge_attr=weight, create_using=G)
|
|
311
313
|
G = G.find_connected_subgraph()
|
|
@@ -323,7 +325,7 @@ class Graph(nx.Graph):
|
|
|
323
325
|
nx.set_node_attributes(G, node_aggregates, name=weight)
|
|
324
326
|
|
|
325
327
|
G = G.edge_subgraph(edges=G.top_k_edges(attribute=weight))
|
|
326
|
-
return G
|
|
328
|
+
return Graph(G)
|
|
327
329
|
|
|
328
330
|
|
|
329
331
|
def plot_network(pd_df: pd.DataFrame,
|
|
@@ -333,15 +335,49 @@ def plot_network(pd_df: pd.DataFrame,
|
|
|
333
335
|
title: str = "Test",
|
|
334
336
|
style: StyleTemplate = NETWORK_STYLE_TEMPLATE,
|
|
335
337
|
sort_by: Optional[str] = None,
|
|
336
|
-
ascending: bool = False,
|
|
338
|
+
ascending: bool = False,
|
|
339
|
+
node_list: Optional[List] = None,
|
|
337
340
|
ax: Optional[Axes] = None) -> Axes:
|
|
341
|
+
if node_list:
|
|
342
|
+
df = pd_df[(pd_df["source"].isin(node_list)) | (pd_df["target"].isin(node_list))]
|
|
343
|
+
else:
|
|
344
|
+
df = pd_df
|
|
345
|
+
validate_dataframe(df, cols=[source, target, weight], sort_by=sort_by)
|
|
338
346
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
graph = Graph.from_pandas_edgelist(pd_df,
|
|
347
|
+
graph = Graph.from_pandas_edgelist(df,
|
|
342
348
|
source=source,
|
|
343
349
|
target=target,
|
|
344
350
|
weight=weight)
|
|
345
|
-
return graph.
|
|
351
|
+
return graph.plot_network(title=title,
|
|
346
352
|
style=style,
|
|
347
353
|
ax=ax)
|
|
354
|
+
|
|
355
|
+
def plot_network_components(pd_df: pd.DataFrame,
|
|
356
|
+
source: str = "source",
|
|
357
|
+
target: str = "target",
|
|
358
|
+
weight: str = "weight",
|
|
359
|
+
title: str = "Test",
|
|
360
|
+
style: StyleTemplate = NETWORK_STYLE_TEMPLATE,
|
|
361
|
+
sort_by: Optional[str] = None,
|
|
362
|
+
node_list: Optional[List] = None,
|
|
363
|
+
ascending: bool = False,
|
|
364
|
+
ax: Optional[List[Axes]] = None) -> List[Axes]:
|
|
365
|
+
if node_list:
|
|
366
|
+
df = pd_df[(pd_df["source"].isin(node_list)) | (pd_df["target"].isin(node_list))]
|
|
367
|
+
else:
|
|
368
|
+
df = pd_df
|
|
369
|
+
validate_dataframe(df, cols=[source, target, weight], sort_by=sort_by)
|
|
370
|
+
|
|
371
|
+
graph = Graph.from_pandas_edgelist(df,
|
|
372
|
+
source=source,
|
|
373
|
+
target=target,
|
|
374
|
+
weight=weight)
|
|
375
|
+
connected_components = nx.connected_components(graph)
|
|
376
|
+
axes=[]
|
|
377
|
+
for connected_component in connected_components:
|
|
378
|
+
if len(connected_component) > 5:
|
|
379
|
+
connected_component_graph = graph.subgraph(node_list=connected_component)
|
|
380
|
+
ax=connected_component_graph.plot_network()
|
|
381
|
+
axes.append(ax)
|
|
382
|
+
return axes
|
|
383
|
+
|
MatplotLibAPI/Pivot.py
CHANGED
|
@@ -10,15 +10,15 @@ from matplotlib.axes import Axes
|
|
|
10
10
|
from matplotlib.dates import DateFormatter, MonthLocator
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
from
|
|
13
|
+
from . import DynamicFuncFormatter, StyleTemplate, generate_ticks, string_formatter, percent_formatter, format_func
|
|
14
|
+
from .. import validate_dataframe
|
|
15
15
|
|
|
16
16
|
PIVOTBARS_STYLE_TEMPLATE = StyleTemplate(
|
|
17
17
|
background_color='black',
|
|
18
18
|
fig_border='darkgrey',
|
|
19
19
|
font_color='white',
|
|
20
20
|
palette='magma',
|
|
21
|
-
format_funcs={"y": percent_formatter,
|
|
21
|
+
format_funcs={"y": percent_formatter,
|
|
22
22
|
"label": string_formatter}
|
|
23
23
|
)
|
|
24
24
|
PIVOTLINES_STYLE_TEMPLATE = StyleTemplate(
|
|
@@ -28,6 +28,7 @@ PIVOTLINES_STYLE_TEMPLATE = StyleTemplate(
|
|
|
28
28
|
format_funcs={"y": percent_formatter, "label": string_formatter}
|
|
29
29
|
)
|
|
30
30
|
|
|
31
|
+
|
|
31
32
|
def plot_pivotbar(pd_df: pd.DataFrame,
|
|
32
33
|
label: str,
|
|
33
34
|
x: str,
|
|
@@ -39,8 +40,8 @@ def plot_pivotbar(pd_df: pd.DataFrame,
|
|
|
39
40
|
ascending: bool = False,
|
|
40
41
|
ax: Optional[Axes] = None):
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
style.format_funcs=format_func(style.format_funcs,label=label,x=x,y=y)
|
|
43
|
+
validate_dataframe(pd_df, cols=[label, x, y], sort_by=sort_by)
|
|
44
|
+
style.format_funcs = format_func(style.format_funcs, label=label, x=x, y=y)
|
|
44
45
|
pivot_df = pd.pivot_table(pd_df, values=y, index=[
|
|
45
46
|
x], columns=[label], aggfunc=agg)
|
|
46
47
|
# Reset index to make x a column again
|
MatplotLibAPI/Table.py
CHANGED
|
@@ -2,7 +2,9 @@ from typing import List, Optional
|
|
|
2
2
|
import pandas as pd
|
|
3
3
|
import matplotlib.pyplot as plt
|
|
4
4
|
from matplotlib.axes import Axes
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
from . import StyleTemplate, string_formatter
|
|
7
|
+
from .. import validate_dataframe
|
|
6
8
|
|
|
7
9
|
TABLE_STYLE_TEMPLATE = StyleTemplate(
|
|
8
10
|
background_color='black',
|
|
@@ -21,7 +23,7 @@ def plot_table(pd_df: pd.DataFrame,
|
|
|
21
23
|
ascending: bool = False,
|
|
22
24
|
ax: Optional[Axes] = None
|
|
23
25
|
) -> Axes:
|
|
24
|
-
|
|
26
|
+
validate_dataframe(pd_df, cols=cols, sort_by=sort_by)
|
|
25
27
|
|
|
26
28
|
if not sort_by:
|
|
27
29
|
sort_by = cols[0]
|
MatplotLibAPI/Timeserie.py
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# Hint for Visual Code Python Interactive window
|
|
2
2
|
# %%
|
|
3
|
+
from typing import Optional
|
|
3
4
|
import pandas as pd
|
|
4
|
-
|
|
5
5
|
import matplotlib.pyplot as plt
|
|
6
6
|
from matplotlib.axes import Axes
|
|
7
7
|
import seaborn as sns
|
|
8
|
-
|
|
9
|
-
from
|
|
8
|
+
|
|
9
|
+
from . import DynamicFuncFormatter, StyleTemplate, string_formatter, bmk_formatter, format_func
|
|
10
|
+
from .. import validate_dataframe
|
|
11
|
+
|
|
10
12
|
|
|
11
13
|
TIMESERIE_STYLE_TEMPLATE = StyleTemplate(
|
|
12
14
|
palette='rocket',
|
|
@@ -26,7 +28,7 @@ def plot_timeserie(pd_df: pd.DataFrame,
|
|
|
26
28
|
ascending: bool = False,
|
|
27
29
|
ax: Optional[Axes] = None) -> Axes:
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
validate_dataframe(pd_df, cols=[label, x, y], sort_by=sort_by)
|
|
30
32
|
style.format_funcs = format_func(style.format_funcs, label=label, x=x, y=y)
|
|
31
33
|
|
|
32
34
|
df = pd_df[[label, x, y]].sort_values(by=[label, x])
|
MatplotLibAPI/Treemap.py
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
# Hint for Visual Code Python Interactive window
|
|
2
|
+
# %%
|
|
3
|
+
from typing import Optional
|
|
2
4
|
import pandas as pd
|
|
3
5
|
import plotly.graph_objects as go
|
|
4
|
-
|
|
6
|
+
|
|
7
|
+
from . import StyleTemplate, string_formatter, percent_formatter
|
|
8
|
+
from .. import validate_dataframe
|
|
9
|
+
|
|
5
10
|
|
|
6
11
|
TREEMAP_STYLE_TEMPLATE = StyleTemplate(
|
|
7
12
|
background_color='black',
|
|
@@ -26,7 +31,7 @@ def plot_treemap(pd_df: pd.DataFrame,
|
|
|
26
31
|
cols = [path, values]
|
|
27
32
|
if color:
|
|
28
33
|
cols.append(color)
|
|
29
|
-
|
|
34
|
+
validate_dataframe(pd_df, cols=cols, sort_by=sort_by)
|
|
30
35
|
if not sort_by:
|
|
31
36
|
sort_by = values
|
|
32
37
|
df = pd_df.sort_values(by=sort_by, ascending=ascending)[
|
|
@@ -35,21 +40,39 @@ def plot_treemap(pd_df: pd.DataFrame,
|
|
|
35
40
|
"parents": [""] * len(df),
|
|
36
41
|
"values": df[values],
|
|
37
42
|
"textinfo": "label",
|
|
38
|
-
"name": title
|
|
43
|
+
"name": title,
|
|
44
|
+
"textfont":
|
|
45
|
+
{"family": style.font_name,
|
|
46
|
+
"size": style.font_size,
|
|
47
|
+
"color": style.font_color}
|
|
48
|
+
}
|
|
39
49
|
|
|
40
|
-
if color:
|
|
41
|
-
|
|
50
|
+
if color and color in pd_df.columns:
|
|
51
|
+
color_data = pd_df[color]
|
|
52
|
+
if pd.api.types.is_categorical_dtype(color_data) or pd.api.types.is_object_dtype(color_data):
|
|
53
|
+
color_data = color_data.astype('category').cat.codes
|
|
54
|
+
elif pd.api.types.is_bool_dtype(color_data):
|
|
55
|
+
color_data = color_data.astype(int)
|
|
56
|
+
data['marker'] = dict(colorscale="Viridis",
|
|
57
|
+
colors=color_data.to_list())
|
|
58
|
+
|
|
59
|
+
g = go.Treemap(data)
|
|
42
60
|
|
|
43
61
|
if not fig:
|
|
44
|
-
fig = go.Figure(
|
|
62
|
+
fig = go.Figure(g)
|
|
45
63
|
else:
|
|
46
|
-
fig.add_trace(
|
|
47
|
-
|
|
64
|
+
fig.add_trace(g)
|
|
65
|
+
|
|
48
66
|
fig.update_layout(
|
|
49
|
-
|
|
67
|
+
title=title,
|
|
50
68
|
plot_bgcolor=style.background_color,
|
|
51
|
-
|
|
52
|
-
|
|
69
|
+
paper_bgcolor=style.background_color,
|
|
70
|
+
font=dict(
|
|
71
|
+
family=style.font_name,
|
|
72
|
+
size=style.font_size,
|
|
73
|
+
color=style.font_color
|
|
74
|
+
),
|
|
75
|
+
showlegend=style.legend if style else True)
|
|
53
76
|
|
|
54
77
|
# Apply color scale
|
|
55
78
|
fig.update_traces(
|
MatplotLibAPI/__init__.py
CHANGED
|
@@ -1,14 +1,301 @@
|
|
|
1
1
|
|
|
2
|
+
from typing import List, Optional, Dict, Callable, Union
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
import pandas as pd
|
|
5
|
+
from pandas.api.extensions import register_dataframe_accessor
|
|
6
|
+
import numpy as np
|
|
2
7
|
|
|
3
|
-
from .
|
|
4
|
-
from .
|
|
5
|
-
from .
|
|
6
|
-
from .
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
from matplotlib.axes import Axes
|
|
9
|
+
from matplotlib.figure import Figure
|
|
10
|
+
from matplotlib.dates import num2date
|
|
11
|
+
from matplotlib.ticker import FuncFormatter
|
|
12
|
+
import plotly.graph_objects as go
|
|
13
|
+
|
|
14
|
+
from . import StyleTemplate
|
|
15
|
+
from .Bubble import plot_bubble, BUBBLE_STYLE_TEMPLATE
|
|
9
16
|
from .Composite import plot_composite_bubble
|
|
10
|
-
from .
|
|
11
|
-
from .
|
|
17
|
+
from .Timeserie import plot_timeserie, TIMESERIE_STYLE_TEMPLATE
|
|
18
|
+
from .Table import plot_table, TABLE_STYLE_TEMPLATE
|
|
19
|
+
from .Network import Graph
|
|
20
|
+
from .Treemap import plot_treemap, TREEMAP_STYLE_TEMPLATE
|
|
21
|
+
|
|
22
|
+
# region Utils
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def format_func(
|
|
26
|
+
format_funcs: Optional[Dict[str, Optional[Callable[[Union[int, float, str]], str]]]],
|
|
27
|
+
label: Optional[str] = None,
|
|
28
|
+
x: Optional[str] = None,
|
|
29
|
+
y: Optional[str] = None,
|
|
30
|
+
z: Optional[str] = None):
|
|
31
|
+
|
|
32
|
+
if label and "label" in format_funcs:
|
|
33
|
+
format_funcs[label] = format_funcs["label"]
|
|
34
|
+
if x and "x" in format_funcs:
|
|
35
|
+
format_funcs[x] = format_funcs["x"]
|
|
36
|
+
if y and "y" in format_funcs:
|
|
37
|
+
format_funcs[y] = format_funcs["y"]
|
|
38
|
+
if z and "z" in format_funcs:
|
|
39
|
+
format_funcs[z] = format_funcs["z"]
|
|
40
|
+
return format_funcs
|
|
41
|
+
|
|
42
|
+
# endregion
|
|
43
|
+
|
|
44
|
+
# region Style
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
MAX_RESULTS = 50
|
|
48
|
+
X_COL = "index"
|
|
49
|
+
Y_COL = "overlap"
|
|
50
|
+
Z_COL = "users"
|
|
51
|
+
FIG_SIZE = (19.2, 10.8)
|
|
52
|
+
BACKGROUND_COLOR = 'black'
|
|
53
|
+
TEXT_COLOR = 'white'
|
|
54
|
+
PALETTE = "Greys_r"
|
|
55
|
+
FONT_SIZE = 14
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass
|
|
59
|
+
class StyleTemplate:
|
|
60
|
+
background_color: str = BACKGROUND_COLOR
|
|
61
|
+
fig_border: str = BACKGROUND_COLOR
|
|
62
|
+
font_name: str = 'Arial'
|
|
63
|
+
font_size: int = FONT_SIZE
|
|
64
|
+
font_color: str = TEXT_COLOR
|
|
65
|
+
palette: str = PALETTE
|
|
66
|
+
legend: bool = True
|
|
67
|
+
xscale: Optional[str] = None
|
|
68
|
+
x_ticks: int = 10
|
|
69
|
+
yscale: Optional[str] = None
|
|
70
|
+
y_ticks: int = 5
|
|
71
|
+
format_funcs: Optional[Dict[str, Optional[Callable[[
|
|
72
|
+
Union[int, float, str]], str]]]] = None
|
|
73
|
+
col_widths: Optional[List[float]] = None
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def font_mapping(self):
|
|
77
|
+
return {0: self.font_size-3,
|
|
78
|
+
1: self.font_size-1,
|
|
79
|
+
2: self.font_size,
|
|
80
|
+
3: self.font_size+1,
|
|
81
|
+
4: self.font_size+3}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class DynamicFuncFormatter(FuncFormatter):
|
|
85
|
+
def __init__(self, func_name):
|
|
86
|
+
super().__init__(func_name)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def percent_formatter(val, pos: Optional[int] = None):
|
|
90
|
+
if val*100 <= 0.1: # For 0.1%
|
|
91
|
+
return f"{val*100:.2f}%"
|
|
92
|
+
elif val*100 <= 1: # For 1%
|
|
93
|
+
return f"{val*100:.1f}%"
|
|
94
|
+
else:
|
|
95
|
+
return f"{val*100:.0f}%"
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def bmk_formatter(val, pos: Optional[int] = None):
|
|
99
|
+
if val >= 1_000_000_000: # Billions
|
|
100
|
+
return f"{val / 1_000_000_000:.2f}B"
|
|
101
|
+
elif val >= 1_000_000: # Millions
|
|
102
|
+
return f"{val / 1_000_000:.1f}M"
|
|
103
|
+
elif val >= 1_000: # Thousands
|
|
104
|
+
return f"{val / 1_000:.1f}K"
|
|
105
|
+
else:
|
|
106
|
+
return f"{int(val)}"
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def integer_formatter(value, pos: Optional[int] = None):
|
|
110
|
+
return f"{int(value)}"
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def string_formatter(value, pos: Optional[int] = None):
|
|
114
|
+
return str(value).replace("-", " ").replace("_", " ").title()
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def yy_mm__formatter(x, pos: Optional[int] = None):
|
|
118
|
+
return num2date(x).strftime('%Y-%m')
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def yy_mm_dd__formatter(x, pos: Optional[int] = None):
|
|
122
|
+
return num2date(x).strftime('%Y-%m-%D')
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def percent_formatter(x, pos: Optional[int] = None):
|
|
126
|
+
return f"{x * 100:.0f}%"
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def generate_ticks(min_val, max_val, num_ticks="10"):
|
|
130
|
+
# Identify the type of the input
|
|
131
|
+
try:
|
|
132
|
+
min_val = float(min_val)
|
|
133
|
+
max_val = float(max_val)
|
|
134
|
+
is_date = False
|
|
135
|
+
except ValueError:
|
|
136
|
+
is_date = True
|
|
137
|
+
|
|
138
|
+
# Convert string inputs to appropriate numerical or date types
|
|
139
|
+
num_ticks = int(num_ticks)
|
|
140
|
+
|
|
141
|
+
if is_date:
|
|
142
|
+
min_val = pd.Timestamp(min_val).to_datetime64()
|
|
143
|
+
max_val = pd.Timestamp(max_val).to_datetime64()
|
|
144
|
+
data_range = (max_val - min_val).astype('timedelta64[D]').astype(int)
|
|
145
|
+
else:
|
|
146
|
+
data_range = max_val - min_val
|
|
147
|
+
|
|
148
|
+
# Calculate a nice step size
|
|
149
|
+
step_size = data_range / (num_ticks - 1)
|
|
150
|
+
|
|
151
|
+
# If date, convert back to datetime
|
|
152
|
+
if is_date:
|
|
153
|
+
ticks = pd.date_range(
|
|
154
|
+
start=min_val, periods=num_ticks, freq=f"{step_size}D")
|
|
155
|
+
else:
|
|
156
|
+
# Round the step size to a "nice" number
|
|
157
|
+
exponent = np.floor(np.log10(step_size))
|
|
158
|
+
fraction = step_size / 10**exponent
|
|
159
|
+
nice_fraction = round(fraction)
|
|
160
|
+
|
|
161
|
+
# Create nice step size
|
|
162
|
+
nice_step = nice_fraction * 10**exponent
|
|
163
|
+
|
|
164
|
+
# Generate the tick marks based on the nice step size
|
|
165
|
+
ticks = np.arange(min_val, max_val + nice_step, nice_step)
|
|
166
|
+
|
|
167
|
+
return ticks
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
# endregion
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
@register_dataframe_accessor("mpl")
|
|
174
|
+
class DataFrameAccessor:
|
|
175
|
+
|
|
176
|
+
def __init__(self, pd_df: pd.DataFrame):
|
|
177
|
+
self._obj = pd_df
|
|
178
|
+
|
|
179
|
+
def plot_bubble(self,
|
|
180
|
+
label: str,
|
|
181
|
+
x: str,
|
|
182
|
+
y: str,
|
|
183
|
+
z: str,
|
|
184
|
+
title: Optional[str] = None,
|
|
185
|
+
style: StyleTemplate = BUBBLE_STYLE_TEMPLATE,
|
|
186
|
+
max_values: int = 50,
|
|
187
|
+
center_to_mean: bool = False,
|
|
188
|
+
sort_by: Optional[str] = None,
|
|
189
|
+
ascending: bool = False) -> Axes:
|
|
190
|
+
|
|
191
|
+
return plot_bubble(pd_df=self._obj,
|
|
192
|
+
label=label,
|
|
193
|
+
x=x,
|
|
194
|
+
y=y,
|
|
195
|
+
z=z,
|
|
196
|
+
title=title,
|
|
197
|
+
style=style,
|
|
198
|
+
max_values=max_values,
|
|
199
|
+
center_to_mean=center_to_mean,
|
|
200
|
+
sort_by=sort_by,
|
|
201
|
+
ascending=ascending)
|
|
202
|
+
|
|
203
|
+
def plot_composite_bubble(self,
|
|
204
|
+
label: str,
|
|
205
|
+
x: str,
|
|
206
|
+
y: str,
|
|
207
|
+
z: str,
|
|
208
|
+
title: Optional[str] = None,
|
|
209
|
+
style: StyleTemplate = BUBBLE_STYLE_TEMPLATE,
|
|
210
|
+
max_values: int = 100,
|
|
211
|
+
center_to_mean: bool = False,
|
|
212
|
+
sort_by: Optional[str] = None,
|
|
213
|
+
ascending: bool = False) -> Figure:
|
|
214
|
+
|
|
215
|
+
return plot_composite_bubble(pd_df=self._obj,
|
|
216
|
+
label=label,
|
|
217
|
+
x=x,
|
|
218
|
+
y=y,
|
|
219
|
+
z=z,
|
|
220
|
+
title=title,
|
|
221
|
+
style=style,
|
|
222
|
+
max_values=max_values,
|
|
223
|
+
center_to_mean=center_to_mean,
|
|
224
|
+
sort_by=sort_by,
|
|
225
|
+
ascending=ascending)
|
|
226
|
+
|
|
227
|
+
def plot_table(self,
|
|
228
|
+
cols: List[str],
|
|
229
|
+
title: Optional[str] = None,
|
|
230
|
+
style: StyleTemplate = TABLE_STYLE_TEMPLATE,
|
|
231
|
+
max_values: int = 20,
|
|
232
|
+
sort_by: Optional[str] = None,
|
|
233
|
+
ascending: bool = False) -> Axes:
|
|
234
|
+
|
|
235
|
+
return plot_table(pd_df=self._obj,
|
|
236
|
+
cols=cols,
|
|
237
|
+
title=title,
|
|
238
|
+
style=style,
|
|
239
|
+
max_values=max_values,
|
|
240
|
+
sort_by=sort_by,
|
|
241
|
+
ascending=ascending)
|
|
242
|
+
|
|
243
|
+
def plot_timeserie(self,
|
|
244
|
+
label: str,
|
|
245
|
+
x: str,
|
|
246
|
+
y: str,
|
|
247
|
+
title: Optional[str] = None,
|
|
248
|
+
style: StyleTemplate = TIMESERIE_STYLE_TEMPLATE,
|
|
249
|
+
max_values: int = 100,
|
|
250
|
+
sort_by: Optional[str] = None,
|
|
251
|
+
ascending: bool = False) -> Axes:
|
|
252
|
+
|
|
253
|
+
return plot_timeserie(pd_df=self._obj,
|
|
254
|
+
label=label,
|
|
255
|
+
x=x,
|
|
256
|
+
y=y,
|
|
257
|
+
title=title,
|
|
258
|
+
style=style,
|
|
259
|
+
max_values=max_values,
|
|
260
|
+
sort_by=sort_by,
|
|
261
|
+
ascending=ascending)
|
|
262
|
+
|
|
263
|
+
def plot_network(self,
|
|
264
|
+
source: str = "source",
|
|
265
|
+
target: str = "target",
|
|
266
|
+
weight: str = "weight",
|
|
267
|
+
title: Optional[str] = None,
|
|
268
|
+
style: StyleTemplate = TIMESERIE_STYLE_TEMPLATE,
|
|
269
|
+
max_values: int = 20,
|
|
270
|
+
sort_by: Optional[str] = None,
|
|
271
|
+
ascending: bool = False) -> Axes:
|
|
272
|
+
|
|
273
|
+
graph = Graph.from_pandas_edgelist(df=self._obj,
|
|
274
|
+
source=source,
|
|
275
|
+
target=target,
|
|
276
|
+
weight=weight)
|
|
277
|
+
|
|
278
|
+
return graph.plotX(title, style)
|
|
279
|
+
|
|
280
|
+
def plot_treemap(self,
|
|
281
|
+
path: str,
|
|
282
|
+
values: str,
|
|
283
|
+
style: StyleTemplate = TREEMAP_STYLE_TEMPLATE,
|
|
284
|
+
title: Optional[str] = None,
|
|
285
|
+
color: Optional[str] = None,
|
|
286
|
+
max_values: int = 100,
|
|
287
|
+
sort_by: Optional[str] = None,
|
|
288
|
+
ascending: bool = False) -> go.Figure:
|
|
289
|
+
return plot_treemap(pd_df=self._obj,
|
|
290
|
+
path=path,
|
|
291
|
+
values=values,
|
|
292
|
+
title=title,
|
|
293
|
+
style=style,
|
|
294
|
+
color=color,
|
|
295
|
+
max_values=max_values,
|
|
296
|
+
sort_by=sort_by,
|
|
297
|
+
ascending=ascending)
|
|
298
|
+
|
|
12
299
|
|
|
13
|
-
__all__ = ["plot_bubble", "plot_timeserie", "plot_table", "plot_network",
|
|
14
|
-
"plot_pivotbar", "plot_treemap","plot_composite_bubble", "StyleTemplate", "
|
|
300
|
+
__all__ = ["validate_dataframe", "plot_bubble", "plot_timeserie", "plot_table", "plot_network", "plot_network_components",
|
|
301
|
+
"plot_pivotbar", "plot_treemap", "plot_composite_bubble", "StyleTemplate", "DataFrameAccessor"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: MatplotLibAPI
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.1
|
|
4
4
|
Requires-Python: >=3.7
|
|
5
5
|
Description-Content-Type: text/markdown
|
|
6
6
|
License-File: LICENSE
|
|
@@ -10,6 +10,14 @@ Requires-Dist: networkx
|
|
|
10
10
|
Requires-Dist: plotly
|
|
11
11
|
Requires-Dist: seaborn
|
|
12
12
|
Requires-Dist: scikit-learn
|
|
13
|
+
Requires-Dist: kaleido
|
|
14
|
+
Requires-Dist: nbformat
|
|
13
15
|
|
|
14
16
|
# MatplotLibAPI
|
|
15
|
-
Simple
|
|
17
|
+
Simple pandas Dataframe to generate plots:
|
|
18
|
+
Bubble (Scatter plot)
|
|
19
|
+
Network (Graph)
|
|
20
|
+
pivot
|
|
21
|
+
Table
|
|
22
|
+
Timeserie
|
|
23
|
+
Treemap
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
MatplotLibAPI/Bubble.py,sha256=dYmmtYKECFcraAwfStc5Se9TmxsCUxmRyDS2q3lLxQc,3844
|
|
2
|
+
MatplotLibAPI/Composite.py,sha256=XEW5iaXuqjB1ask_M2ZhGnj8enWcxLmt8nqQdw_HNxE,2848
|
|
3
|
+
MatplotLibAPI/Network.py,sha256=2IHpfTolux84OhJ2xcmROcXFM7lr-ZUH6E_oX8t5AyA,14851
|
|
4
|
+
MatplotLibAPI/Pivot.py,sha256=Bo7ZpkxqoE75e8vpSsKIT5X2Q7lLdfAyy46ox1fARbc,7183
|
|
5
|
+
MatplotLibAPI/Table.py,sha256=RxADNGU_EghQFCxV7Tlk7mYbLRJXPJ7XNK5emjAg8e0,2007
|
|
6
|
+
MatplotLibAPI/Timeserie.py,sha256=SJ2TgaXynbBiwNXjCIbSXlQa9vLh2weyNFW5Xeaknb4,3448
|
|
7
|
+
MatplotLibAPI/Treemap.py,sha256=fOUMeWd8JqI3KhI2mmYg0o0pevBd_af80Im4ILm9wBo,2511
|
|
8
|
+
MatplotLibAPI/__init__.py,sha256=YUSyPpLmu7riEv1X76OLjIhWGtZMK5x0WqaFO-_Oh-g,10081
|
|
9
|
+
MatplotLibAPI-3.1.1.dist-info/LICENSE,sha256=hMErKLb6YZR3lRR5zr-vxeFkvY69QAaafgSpZ5-P1dQ,1067
|
|
10
|
+
MatplotLibAPI-3.1.1.dist-info/METADATA,sha256=dkZ4xZfVEhhf7V7UY1fMXs_SCBIjvo-gIj3c3Lum_yY,462
|
|
11
|
+
MatplotLibAPI-3.1.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
12
|
+
MatplotLibAPI-3.1.1.dist-info/top_level.txt,sha256=MrzbBjDEW48Vb6YhQIqpFYGOhHzQnEIM5Qy2xy2iqew,14
|
|
13
|
+
MatplotLibAPI-3.1.1.dist-info/RECORD,,
|
MatplotLibAPI/Style.py
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
from dataclasses import dataclass
|
|
3
|
-
|
|
4
|
-
from typing import List, Optional, Union, Dict, Callable
|
|
5
|
-
|
|
6
|
-
import numpy as np
|
|
7
|
-
import pandas as pd
|
|
8
|
-
|
|
9
|
-
from matplotlib.dates import num2date
|
|
10
|
-
from matplotlib.ticker import FuncFormatter
|
|
11
|
-
|
|
12
|
-
# region Panda
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def _validate_panda(pd_df: pd.DataFrame,
|
|
16
|
-
cols: List[str],
|
|
17
|
-
sort_by: Optional[str] = None):
|
|
18
|
-
_columns = cols.copy()
|
|
19
|
-
if sort_by and sort_by not in _columns:
|
|
20
|
-
_columns.append(sort_by)
|
|
21
|
-
for col in _columns:
|
|
22
|
-
if col not in pd_df.columns:
|
|
23
|
-
raise AttributeError(f"{col} is not a DataFrame's column")
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def format_func(
|
|
27
|
-
format_funcs: Optional[Dict[str, Optional[Callable[[Union[int, float, str]], str]]]],
|
|
28
|
-
label: Optional[str] = None,
|
|
29
|
-
x: Optional[str] = None,
|
|
30
|
-
y: Optional[str] = None,
|
|
31
|
-
z: Optional[str] = None):
|
|
32
|
-
|
|
33
|
-
if label and "label" in format_funcs:
|
|
34
|
-
format_funcs[label] = format_funcs["label"]
|
|
35
|
-
if x and "x" in format_funcs:
|
|
36
|
-
format_funcs[x] = format_funcs["x"]
|
|
37
|
-
if y and "y" in format_funcs:
|
|
38
|
-
format_funcs[y] = format_funcs["y"]
|
|
39
|
-
if z and "z" in format_funcs:
|
|
40
|
-
format_funcs[z] = format_funcs["z"]
|
|
41
|
-
return format_funcs
|
|
42
|
-
|
|
43
|
-
# endregion
|
|
44
|
-
|
|
45
|
-
# region Style
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
MAX_RESULTS = 50
|
|
49
|
-
X_COL = "index"
|
|
50
|
-
Y_COL = "overlap"
|
|
51
|
-
Z_COL = "users"
|
|
52
|
-
FIG_SIZE = (19.2, 10.8)
|
|
53
|
-
BACKGROUND_COLOR = 'black'
|
|
54
|
-
TEXT_COLOR = 'white'
|
|
55
|
-
PALETTE = "Greys_r"
|
|
56
|
-
FONT_SIZE = 14
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
@dataclass
|
|
60
|
-
class StyleTemplate:
|
|
61
|
-
background_color: str = BACKGROUND_COLOR
|
|
62
|
-
fig_border: str = BACKGROUND_COLOR
|
|
63
|
-
font_name: str = 'Arial'
|
|
64
|
-
font_size: int = FONT_SIZE
|
|
65
|
-
font_color: str = TEXT_COLOR
|
|
66
|
-
palette: str = PALETTE
|
|
67
|
-
legend: bool = True
|
|
68
|
-
xscale: Optional[str] = None
|
|
69
|
-
x_ticks: int = 10
|
|
70
|
-
yscale: Optional[str] = None
|
|
71
|
-
y_ticks: int = 5
|
|
72
|
-
format_funcs: Optional[Dict[str, Optional[Callable[[
|
|
73
|
-
Union[int, float, str]], str]]]] = None
|
|
74
|
-
col_widths: Optional[List[float]] = None
|
|
75
|
-
|
|
76
|
-
@property
|
|
77
|
-
def font_mapping(self):
|
|
78
|
-
return {0: self.font_size-3,
|
|
79
|
-
1: self.font_size-1,
|
|
80
|
-
2: self.font_size,
|
|
81
|
-
3: self.font_size+1,
|
|
82
|
-
4: self.font_size+3}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
class DynamicFuncFormatter(FuncFormatter):
|
|
86
|
-
def __init__(self, func_name):
|
|
87
|
-
super().__init__(func_name)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def percent_formatter(val, pos: Optional[int] = None):
|
|
91
|
-
if val*100 <= 0.1: # For 0.1%
|
|
92
|
-
return f"{val*100:.2f}%"
|
|
93
|
-
elif val*100 <= 1: # For 1%
|
|
94
|
-
return f"{val*100:.1f}%"
|
|
95
|
-
else:
|
|
96
|
-
return f"{val*100:.0f}%"
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def bmk_formatter(val, pos: Optional[int] = None):
|
|
100
|
-
if val >= 1_000_000_000: # Billions
|
|
101
|
-
return f"{val / 1_000_000_000:.2f}B"
|
|
102
|
-
elif val >= 1_000_000: # Millions
|
|
103
|
-
return f"{val / 1_000_000:.1f}M"
|
|
104
|
-
elif val >= 1_000: # Thousands
|
|
105
|
-
return f"{val / 1_000:.1f}K"
|
|
106
|
-
else:
|
|
107
|
-
return f"{int(val)}"
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
def integer_formatter(value, pos: Optional[int] = None):
|
|
111
|
-
return f"{int(value)}"
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
def string_formatter(value, pos: Optional[int] = None):
|
|
115
|
-
return str(value).replace("-", " ").replace("_", " ").title()
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
def yy_mm__formatter(x, pos: Optional[int] = None):
|
|
119
|
-
return num2date(x).strftime('%Y-%m')
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def yy_mm_dd__formatter(x, pos: Optional[int] = None):
|
|
123
|
-
return num2date(x).strftime('%Y-%m-%D')
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
def percent_formatter(x, pos: Optional[int] = None):
|
|
127
|
-
return f"{x * 100:.0f}%"
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def generate_ticks(min_val, max_val, num_ticks="10"):
|
|
131
|
-
# Identify the type of the input
|
|
132
|
-
try:
|
|
133
|
-
min_val = float(min_val)
|
|
134
|
-
max_val = float(max_val)
|
|
135
|
-
is_date = False
|
|
136
|
-
except ValueError:
|
|
137
|
-
is_date = True
|
|
138
|
-
|
|
139
|
-
# Convert string inputs to appropriate numerical or date types
|
|
140
|
-
num_ticks = int(num_ticks)
|
|
141
|
-
|
|
142
|
-
if is_date:
|
|
143
|
-
min_val = pd.Timestamp(min_val).to_datetime64()
|
|
144
|
-
max_val = pd.Timestamp(max_val).to_datetime64()
|
|
145
|
-
data_range = (max_val - min_val).astype('timedelta64[D]').astype(int)
|
|
146
|
-
else:
|
|
147
|
-
data_range = max_val - min_val
|
|
148
|
-
|
|
149
|
-
# Calculate a nice step size
|
|
150
|
-
step_size = data_range / (num_ticks - 1)
|
|
151
|
-
|
|
152
|
-
# If date, convert back to datetime
|
|
153
|
-
if is_date:
|
|
154
|
-
ticks = pd.date_range(
|
|
155
|
-
start=min_val, periods=num_ticks, freq=f"{step_size}D")
|
|
156
|
-
else:
|
|
157
|
-
# Round the step size to a "nice" number
|
|
158
|
-
exponent = np.floor(np.log10(step_size))
|
|
159
|
-
fraction = step_size / 10**exponent
|
|
160
|
-
nice_fraction = round(fraction)
|
|
161
|
-
|
|
162
|
-
# Create nice step size
|
|
163
|
-
nice_step = nice_fraction * 10**exponent
|
|
164
|
-
|
|
165
|
-
# Generate the tick marks based on the nice step size
|
|
166
|
-
ticks = np.arange(min_val, max_val + nice_step, nice_step)
|
|
167
|
-
|
|
168
|
-
return ticks
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
# endregion
|
MatplotLibAPI/pdAccessor.py
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import logging
|
|
3
|
-
import warnings
|
|
4
|
-
|
|
5
|
-
from typing import Optional, List
|
|
6
|
-
import pandas as pd
|
|
7
|
-
|
|
8
|
-
from matplotlib.axes import Axes
|
|
9
|
-
from matplotlib.figure import Figure
|
|
10
|
-
import plotly.graph_objects as go
|
|
11
|
-
from .Style import StyleTemplate
|
|
12
|
-
from .Bubble import plot_bubble, BUBBLE_STYLE_TEMPLATE
|
|
13
|
-
from .Composite import plot_composite_bubble
|
|
14
|
-
from .Timeserie import plot_timeserie, TIMESERIE_STYLE_TEMPLATE
|
|
15
|
-
from .Table import plot_table, TABLE_STYLE_TEMPLATE
|
|
16
|
-
from .Network import Graph
|
|
17
|
-
from .Treemap import plot_treemap, TREEMAP_STYLE_TEMPLATE
|
|
18
|
-
|
|
19
|
-
warnings.filterwarnings('ignore')
|
|
20
|
-
logging.getLogger().setLevel(logging.WARNING)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@pd.api.extensions.register_dataframe_accessor("mpl")
|
|
24
|
-
class MatPlotLibAccessor:
|
|
25
|
-
|
|
26
|
-
def __init__(self, pd_df: pd.DataFrame):
|
|
27
|
-
self._obj = pd_df
|
|
28
|
-
|
|
29
|
-
def plot_bubble(self,
|
|
30
|
-
label: str,
|
|
31
|
-
x: str,
|
|
32
|
-
y: str,
|
|
33
|
-
z: str,
|
|
34
|
-
title: Optional[str] = None,
|
|
35
|
-
style: StyleTemplate = BUBBLE_STYLE_TEMPLATE,
|
|
36
|
-
max_values: int = 50,
|
|
37
|
-
center_to_mean: bool = False,
|
|
38
|
-
sort_by: Optional[str] = None,
|
|
39
|
-
ascending: bool = False) -> Axes:
|
|
40
|
-
|
|
41
|
-
return plot_bubble(pd_df=self._obj,
|
|
42
|
-
label=label,
|
|
43
|
-
x=x,
|
|
44
|
-
y=y,
|
|
45
|
-
z=z,
|
|
46
|
-
title=title,
|
|
47
|
-
style=style,
|
|
48
|
-
max_values=max_values,
|
|
49
|
-
center_to_mean=center_to_mean,
|
|
50
|
-
sort_by=sort_by,
|
|
51
|
-
ascending=ascending)
|
|
52
|
-
|
|
53
|
-
def plot_composite_bubble(self,
|
|
54
|
-
label: str,
|
|
55
|
-
x: str,
|
|
56
|
-
y: str,
|
|
57
|
-
z: str,
|
|
58
|
-
title: Optional[str] = None,
|
|
59
|
-
style: StyleTemplate = BUBBLE_STYLE_TEMPLATE,
|
|
60
|
-
max_values: int = 100,
|
|
61
|
-
center_to_mean: bool = False,
|
|
62
|
-
sort_by: Optional[str] = None,
|
|
63
|
-
ascending: bool = False) -> Figure:
|
|
64
|
-
|
|
65
|
-
return plot_composite_bubble(pd_df=self._obj,
|
|
66
|
-
label=label,
|
|
67
|
-
x=x,
|
|
68
|
-
y=y,
|
|
69
|
-
z=z,
|
|
70
|
-
title=title,
|
|
71
|
-
style=style,
|
|
72
|
-
max_values=max_values,
|
|
73
|
-
center_to_mean=center_to_mean,
|
|
74
|
-
sort_by=sort_by,
|
|
75
|
-
ascending=ascending)
|
|
76
|
-
|
|
77
|
-
def plot_table(self,
|
|
78
|
-
cols: List[str],
|
|
79
|
-
title: Optional[str] = None,
|
|
80
|
-
style: StyleTemplate = TABLE_STYLE_TEMPLATE,
|
|
81
|
-
max_values: int = 20,
|
|
82
|
-
sort_by: Optional[str] = None,
|
|
83
|
-
ascending: bool = False) -> Axes:
|
|
84
|
-
|
|
85
|
-
return plot_table(pd_df=self._obj,
|
|
86
|
-
cols=cols,
|
|
87
|
-
title=title,
|
|
88
|
-
style=style,
|
|
89
|
-
max_values=max_values,
|
|
90
|
-
sort_by=sort_by,
|
|
91
|
-
ascending=ascending)
|
|
92
|
-
|
|
93
|
-
def plot_timeserie(self,
|
|
94
|
-
label: str,
|
|
95
|
-
x: str,
|
|
96
|
-
y: str,
|
|
97
|
-
title: Optional[str] = None,
|
|
98
|
-
style: StyleTemplate = TIMESERIE_STYLE_TEMPLATE,
|
|
99
|
-
max_values: int = 100,
|
|
100
|
-
sort_by: Optional[str] = None,
|
|
101
|
-
ascending: bool = False) -> Axes:
|
|
102
|
-
|
|
103
|
-
return plot_timeserie(pd_df=self._obj,
|
|
104
|
-
label=label,
|
|
105
|
-
x=x,
|
|
106
|
-
y=y,
|
|
107
|
-
title=title,
|
|
108
|
-
style=style,
|
|
109
|
-
max_values=max_values,
|
|
110
|
-
sort_by=sort_by,
|
|
111
|
-
ascending=ascending)
|
|
112
|
-
|
|
113
|
-
def plot_network(self,
|
|
114
|
-
source: str = "source",
|
|
115
|
-
target: str = "target",
|
|
116
|
-
weight: str = "weight",
|
|
117
|
-
title: Optional[str] = None,
|
|
118
|
-
style: StyleTemplate = TIMESERIE_STYLE_TEMPLATE,
|
|
119
|
-
max_values: int = 20,
|
|
120
|
-
sort_by: Optional[str] = None,
|
|
121
|
-
ascending: bool = False) -> Axes:
|
|
122
|
-
|
|
123
|
-
graph = Graph.from_pandas_edgelist(df=self._obj,
|
|
124
|
-
source=source,
|
|
125
|
-
target=target,
|
|
126
|
-
weight=weight)
|
|
127
|
-
|
|
128
|
-
return graph.plotX(title, style)
|
|
129
|
-
|
|
130
|
-
def plot_treemap(self,
|
|
131
|
-
path: str,
|
|
132
|
-
values: str,
|
|
133
|
-
style: StyleTemplate = TREEMAP_STYLE_TEMPLATE,
|
|
134
|
-
title: Optional[str] = None,
|
|
135
|
-
color: Optional[str] = None,
|
|
136
|
-
max_values: int = 100,
|
|
137
|
-
sort_by: Optional[str] = None,
|
|
138
|
-
ascending: bool = False) ->go.Figure:
|
|
139
|
-
return plot_treemap(pd_df=self._obj,
|
|
140
|
-
path=path,
|
|
141
|
-
values=values,
|
|
142
|
-
title=title,
|
|
143
|
-
style=style,
|
|
144
|
-
color=color,
|
|
145
|
-
max_values=max_values,
|
|
146
|
-
sort_by=sort_by,
|
|
147
|
-
ascending=ascending)
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
MatplotLibAPI/Bubble.py,sha256=2PIwL0stzFC7knqdMHBBm99DXPXtBJK-xmpxmVlInYw,3830
|
|
2
|
-
MatplotLibAPI/Composite.py,sha256=M_AaBdn9cfMIOGZBg4_twRS9VU9jbgS6cs9E5l3ObOQ,2763
|
|
3
|
-
MatplotLibAPI/Network.py,sha256=fq1-LfDKy3oC5JzqU7IyZudgR2plmziigjpm2TzEA3U,13286
|
|
4
|
-
MatplotLibAPI/Pivot.py,sha256=8jRYdlvw8otrJ1hYBAaKQJoN84xe-YfroXmgRLykMmQ,7162
|
|
5
|
-
MatplotLibAPI/Style.py,sha256=xtw71VWHSQEvts1nJdKR0c_9Rqef6EGkyyvgdTK5M7c,4632
|
|
6
|
-
MatplotLibAPI/Table.py,sha256=Az5uX-ViqzJPTBym4QnUzn5PD5LEsVzQ9WohcSDFcK4,1990
|
|
7
|
-
MatplotLibAPI/Timeserie.py,sha256=HRFHs_WzaZzLmWVVMBKVMP5M3oglsr1R9Ni53X7_HLI,3432
|
|
8
|
-
MatplotLibAPI/Treemap.py,sha256=diCx5270ENBObO3eWlLlpaHWUWcSgMT34vEwWTxTDAE,1799
|
|
9
|
-
MatplotLibAPI/__init__.py,sha256=PDobJg0sw7BjgSQk7p7kkjombghs3D_m-CCk2oeUt_s,506
|
|
10
|
-
MatplotLibAPI/pdAccessor.py,sha256=5duWsURQKgNuwCz1p0ge2GbAXHSHl8e38zJn6NSVAGg,5745
|
|
11
|
-
MatplotLibAPI-3.1.0.dist-info/LICENSE,sha256=hMErKLb6YZR3lRR5zr-vxeFkvY69QAaafgSpZ5-P1dQ,1067
|
|
12
|
-
MatplotLibAPI-3.1.0.dist-info/METADATA,sha256=UvD4nRviP67nS7KnDWa1Dcmt8PygsjCUs6cioLgHQv4,319
|
|
13
|
-
MatplotLibAPI-3.1.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
14
|
-
MatplotLibAPI-3.1.0.dist-info/top_level.txt,sha256=MrzbBjDEW48Vb6YhQIqpFYGOhHzQnEIM5Qy2xy2iqew,14
|
|
15
|
-
MatplotLibAPI-3.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|