MatplotLibAPI 2.0.2__py3-none-any.whl → 3.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.
- MatplotLibAPI/Bubble.py +121 -102
- MatplotLibAPI/Composite.py +71 -102
- MatplotLibAPI/Network.py +61 -32
- MatplotLibAPI/Pivot.py +84 -94
- MatplotLibAPI/Style.py +171 -0
- MatplotLibAPI/Table.py +53 -58
- MatplotLibAPI/Timeserie.py +97 -0
- MatplotLibAPI/__init__.py +13 -0
- MatplotLibAPI/pdAccessor.py +125 -0
- {MatplotLibAPI-2.0.2.dist-info → MatplotLibAPI-3.0.0.dist-info}/METADATA +1 -1
- MatplotLibAPI-3.0.0.dist-info/RECORD +14 -0
- {MatplotLibAPI-2.0.2.dist-info → MatplotLibAPI-3.0.0.dist-info}/WHEEL +1 -1
- MatplotLibAPI/TimeSeries.py +0 -136
- MatplotLibAPI/Utils.py +0 -204
- MatplotLibAPI-2.0.2.dist-info/RECORD +0 -13
- {MatplotLibAPI-2.0.2.dist-info → MatplotLibAPI-3.0.0.dist-info}/LICENSE +0 -0
- {MatplotLibAPI-2.0.2.dist-info → MatplotLibAPI-3.0.0.dist-info}/top_level.txt +0 -0
MatplotLibAPI/Bubble.py
CHANGED
|
@@ -1,108 +1,127 @@
|
|
|
1
|
+
# Hint for Visual Code Python Interactive window
|
|
2
|
+
# %%
|
|
1
3
|
|
|
2
|
-
|
|
3
|
-
from typing import List, Optional, Union
|
|
4
|
-
|
|
5
|
-
import numpy as np
|
|
6
4
|
import pandas as pd
|
|
7
|
-
import
|
|
8
|
-
from sklearn.preprocessing import StandardScaler
|
|
9
|
-
|
|
5
|
+
import matplotlib.pyplot as plt
|
|
10
6
|
from matplotlib.axes import Axes
|
|
11
|
-
|
|
12
|
-
from
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if style.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
+
|
|
11
|
+
|
|
12
|
+
BUBBLE_STYLE_TEMPLATE = StyleTemplate(
|
|
13
|
+
format_funcs={"label": string_formatter,
|
|
14
|
+
"x": bmk_formatter,
|
|
15
|
+
"y": percent_formatter,
|
|
16
|
+
"label": string_formatter,
|
|
17
|
+
"z": bmk_formatter},
|
|
18
|
+
yscale="log",
|
|
19
|
+
y_ticks=8,
|
|
20
|
+
x_ticks=8
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def plot_bubble(
|
|
25
|
+
pd_df: pd.DataFrame,
|
|
26
|
+
label: str,
|
|
27
|
+
x: str,
|
|
28
|
+
y: str,
|
|
29
|
+
z: str,
|
|
30
|
+
title: Optional[str] = "Test",
|
|
31
|
+
style: StyleTemplate = BUBBLE_STYLE_TEMPLATE,
|
|
32
|
+
max_values: int = BUBBLE_STYLE_TEMPLATE,
|
|
33
|
+
center_to_mean: bool = False,
|
|
34
|
+
sort_by: Optional[str] = None,
|
|
35
|
+
ascending: bool = False,
|
|
36
|
+
ax: Optional[Axes] = None):
|
|
37
|
+
|
|
38
|
+
_validate_panda(pd_df, cols=[label, x, y, z], sort_by=sort_by)
|
|
39
|
+
style.format_funcs = format_func(
|
|
40
|
+
style.format_funcs, label=label, x=x, y=y, z=z)
|
|
41
|
+
if not sort_by:
|
|
42
|
+
sort_by = z
|
|
43
|
+
|
|
44
|
+
plot_df = pd_df[[label, x, y, z]].sort_values(
|
|
45
|
+
by=sort_by, ascending=ascending).head(max_values)
|
|
46
|
+
if center_to_mean:
|
|
47
|
+
x_col_mean = plot_df[x].mean()
|
|
48
|
+
plot_df[x] = plot_df[x] - x_col_mean
|
|
49
|
+
plot_df['quintile'] = pd.qcut(
|
|
50
|
+
plot_df[z], 5, labels=False)
|
|
51
|
+
|
|
52
|
+
# styling
|
|
53
|
+
|
|
54
|
+
plot_df["fontsize"] = plot_df['quintile'].map(style.font_mapping)
|
|
55
|
+
|
|
56
|
+
if not ax:
|
|
57
|
+
ax = plt.gca()
|
|
58
|
+
|
|
59
|
+
ax = sns.scatterplot(
|
|
60
|
+
data=plot_df,
|
|
61
|
+
x=x,
|
|
62
|
+
y=y,
|
|
63
|
+
size=z,
|
|
64
|
+
hue='quintile',
|
|
65
|
+
sizes=(100, 2000),
|
|
66
|
+
legend=False,
|
|
67
|
+
palette=sns.color_palette(style.palette, as_cmap=True),
|
|
68
|
+
edgecolor=style.background_color,
|
|
69
|
+
ax=ax)
|
|
70
|
+
ax.set_facecolor(style.background_color)
|
|
71
|
+
if style.xscale:
|
|
72
|
+
ax.set(xscale=style.xscale)
|
|
73
|
+
if style.yscale:
|
|
74
|
+
ax.set(yscale=style.yscale)
|
|
75
|
+
|
|
76
|
+
x_min = pd_df[x].min()
|
|
77
|
+
x_max = pd_df[x].max()
|
|
78
|
+
x_mean = pd_df[x].mean()
|
|
79
|
+
ax.set_xticks(generate_ticks(x_min, x_max, num_ticks=style.x_ticks))
|
|
80
|
+
ax.xaxis.grid(True, "major", linewidth=.5, color=style.font_color)
|
|
81
|
+
if style.format_funcs.get("x"):
|
|
82
|
+
ax.xaxis.set_major_formatter(
|
|
83
|
+
DynamicFuncFormatter(style.format_funcs.get("x")))
|
|
84
|
+
|
|
85
|
+
y_min = pd_df[y].min()
|
|
86
|
+
y_max = pd_df[y].max()
|
|
87
|
+
y_mean = pd_df[y].mean()
|
|
88
|
+
ax.set_yticks(generate_ticks(y_min, y_max, num_ticks=style.y_ticks))
|
|
89
|
+
ax.yaxis.grid(True, "major", linewidth=.5, color=style.font_color)
|
|
90
|
+
if style.format_funcs.get("y"):
|
|
91
|
+
ax.yaxis.set_major_formatter(
|
|
92
|
+
DynamicFuncFormatter(style.format_funcs.get("y")))
|
|
93
|
+
|
|
94
|
+
ax.tick_params(axis='both',
|
|
95
|
+
which='major',
|
|
96
|
+
colors=style.font_color,
|
|
97
|
+
labelsize=style.font_size)
|
|
98
|
+
|
|
99
|
+
ax.vlines(x=x_mean,
|
|
100
|
+
ymin=y_min,
|
|
101
|
+
ymax=y_max,
|
|
102
|
+
linestyle='--',
|
|
103
|
+
colors=style.font_color)
|
|
104
|
+
ax.hlines(y=y_mean,
|
|
105
|
+
xmin=x_min,
|
|
106
|
+
xmax=x_max,
|
|
107
|
+
linestyle='--',
|
|
108
|
+
colors=style.font_color)
|
|
109
|
+
|
|
110
|
+
for index, row in plot_df.iterrows():
|
|
111
|
+
x_value = row[x]
|
|
112
|
+
y_value = row[y]
|
|
113
|
+
s_value = str(row[label])
|
|
114
|
+
if style.format_funcs.get("label"):
|
|
115
|
+
s_value = style.format_funcs.get("label")(s_value)
|
|
116
|
+
fs = row["fontsize"]
|
|
117
|
+
ax.text(x_value,
|
|
118
|
+
y_value,
|
|
119
|
+
s_value,
|
|
120
|
+
horizontalalignment='center',
|
|
121
|
+
fontdict={'color': style.font_color, 'fontsize': fs})
|
|
122
|
+
if title:
|
|
123
|
+
ax.set_title(title, color=style.font_color, fontsize=style.font_size*2)
|
|
106
124
|
return ax
|
|
107
125
|
|
|
126
|
+
|
|
108
127
|
# endregion
|
MatplotLibAPI/Composite.py
CHANGED
|
@@ -1,109 +1,78 @@
|
|
|
1
1
|
# Hint for Visual Code Python Interactive window
|
|
2
2
|
# %%
|
|
3
3
|
import matplotlib.pyplot as plt
|
|
4
|
+
from matplotlib.figure import Figure
|
|
4
5
|
import pandas as pd
|
|
5
|
-
from .Bubble import plot_bubble
|
|
6
|
+
from .Bubble import plot_bubble, BUBBLE_STYLE_TEMPLATE
|
|
6
7
|
from .Table import plot_table
|
|
7
|
-
from typing import
|
|
8
|
-
from
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
fig.tight_layout()
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def plot_composite_12(plot_func1, plot_func2, plot_func3,
|
|
80
|
-
data1, data2, data3,
|
|
81
|
-
metrics1, metrics2, metrics3,
|
|
82
|
-
highlights: Optional[List[str]] = None,
|
|
83
|
-
font_size: int = 12,
|
|
84
|
-
fig_title: str = 'Bubble Plot',
|
|
85
|
-
fig_background_color: str = 'skyblue',
|
|
86
|
-
fig_border: str = 'steelblue',
|
|
87
|
-
font_name: str = 'Arial',
|
|
88
|
-
font_color: str = 'black') -> None:
|
|
89
|
-
|
|
90
|
-
# Create a new figure and define the grid
|
|
91
|
-
fig = plt.figure(fig_title, figsize=(10, 10))
|
|
92
|
-
axgrid = fig.add_gridspec(5, 4)
|
|
93
|
-
|
|
94
|
-
# Create individual axes based on the grid
|
|
95
|
-
ax0 = fig.add_subplot(axgrid[0:3, :])
|
|
96
|
-
ax1 = fig.add_subplot(axgrid[3:, :2])
|
|
97
|
-
ax2 = fig.add_subplot(axgrid[3:, 2:])
|
|
98
|
-
|
|
99
|
-
# Call the individual plot functions with the respective axes and data
|
|
100
|
-
plot_func1(ax=ax0, data=data1, metrics=metrics1, highlights=highlights, font_size=font_size, fig_background_color=fig_background_color,
|
|
101
|
-
fig_border=fig_border, font_name=font_name, font_color=font_color)
|
|
102
|
-
plot_func2(ax=ax1, data=data2, metrics=metrics2, highlights=highlights, font_size=font_size, fig_background_color=fig_background_color,
|
|
103
|
-
fig_border=fig_border, font_name=font_name, font_color=font_color)
|
|
104
|
-
plot_func3(ax=ax2, data=data3, metrics=metrics3, highlights=highlights, font_size=font_size, fig_background_color=fig_background_color,
|
|
105
|
-
fig_border=fig_border, font_name=font_name, font_color=font_color)
|
|
106
|
-
|
|
107
|
-
fig.suptitle(fig_title, fontsize=16)
|
|
8
|
+
from typing import Optional, Tuple
|
|
9
|
+
from .Style import StyleTemplate, _validate_panda,format_func
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def plot_composite_bubble(
|
|
13
|
+
pd_df: pd.DataFrame,
|
|
14
|
+
label: str,
|
|
15
|
+
x: str,
|
|
16
|
+
y: str,
|
|
17
|
+
z: str,
|
|
18
|
+
title: Optional[str] = "Test",
|
|
19
|
+
style: StyleTemplate = BUBBLE_STYLE_TEMPLATE,
|
|
20
|
+
max_values: int = 50,
|
|
21
|
+
center_to_mean: bool = False,
|
|
22
|
+
sort_by: Optional[str] = None,
|
|
23
|
+
ascending: bool = False,
|
|
24
|
+
table_rows: int = 10,
|
|
25
|
+
figsize: Tuple[float, float] = (19.2, 10.8)) -> Figure:
|
|
26
|
+
|
|
27
|
+
_validate_panda(pd_df, cols=[label, x, y, z], sort_by=sort_by)
|
|
28
|
+
style.format_funcs=format_func(style.format_funcs,label=label,x=x,y=y)
|
|
29
|
+
fig = plt.figure(figsize=figsize)
|
|
30
|
+
fig.patch.set_facecolor("black")
|
|
31
|
+
grid = plt.GridSpec(2, 2, height_ratios=[2, 1], width_ratios=[1, 1])
|
|
32
|
+
ax = fig.add_subplot(grid[0, 0:])
|
|
33
|
+
ax = plot_bubble(pd_df=pd_df,
|
|
34
|
+
label=label,
|
|
35
|
+
x=x,
|
|
36
|
+
y=y,
|
|
37
|
+
z=z,
|
|
38
|
+
title=title,
|
|
39
|
+
style=style,
|
|
40
|
+
max_values=max_values,
|
|
41
|
+
center_to_mean=center_to_mean,
|
|
42
|
+
sort_by=sort_by,
|
|
43
|
+
ascending=ascending,
|
|
44
|
+
ax=ax)
|
|
45
|
+
|
|
46
|
+
if "label" in style.format_funcs:
|
|
47
|
+
style.format_funcs[label] = style.format_funcs["label"]
|
|
48
|
+
if "x" in style.format_funcs:
|
|
49
|
+
style.format_funcs[x] = style.format_funcs["x"]
|
|
50
|
+
if "y" in style.format_funcs:
|
|
51
|
+
style.format_funcs[y] = style.format_funcs["y"]
|
|
52
|
+
if "z" in style.format_funcs:
|
|
53
|
+
style.format_funcs[z] = style.format_funcs["z"]
|
|
54
|
+
|
|
55
|
+
ax2 = fig.add_subplot(grid[1, 0])
|
|
56
|
+
ax2 = plot_table(
|
|
57
|
+
pd_df=pd_df,
|
|
58
|
+
cols=[label, z, y, x],
|
|
59
|
+
title=f"Top {table_rows}",
|
|
60
|
+
ax=ax2,
|
|
61
|
+
sort_by=sort_by,
|
|
62
|
+
ascending=False,
|
|
63
|
+
max_values=table_rows,
|
|
64
|
+
style=style
|
|
65
|
+
)
|
|
66
|
+
ax3 = fig.add_subplot(grid[1, 1])
|
|
67
|
+
ax3 = plot_table(
|
|
68
|
+
pd_df=pd_df,
|
|
69
|
+
cols=[label, z, y, x],
|
|
70
|
+
title=f"Worst {table_rows}",
|
|
71
|
+
ax=ax3,
|
|
72
|
+
sort_by=sort_by,
|
|
73
|
+
ascending=True,
|
|
74
|
+
max_values=table_rows,
|
|
75
|
+
style=style
|
|
76
|
+
)
|
|
108
77
|
fig.tight_layout()
|
|
109
78
|
return fig
|
MatplotLibAPI/Network.py
CHANGED
|
@@ -4,19 +4,27 @@ from collections.abc import Iterable
|
|
|
4
4
|
from typing import Any, Dict, List, Optional, Tuple
|
|
5
5
|
|
|
6
6
|
import matplotlib.pyplot as plt
|
|
7
|
+
from matplotlib.axes import Axes
|
|
8
|
+
import seaborn as sns
|
|
7
9
|
import networkx as nx
|
|
8
10
|
import numpy as np
|
|
9
11
|
import pandas as pd
|
|
10
12
|
from networkx import Graph
|
|
11
13
|
from networkx.classes.graph import Graph
|
|
12
14
|
|
|
15
|
+
|
|
16
|
+
from .Style import StyleTemplate, string_formatter, _validate_panda,format_func
|
|
17
|
+
|
|
18
|
+
NETWORK_STYLE_TEMPLATE = StyleTemplate(
|
|
19
|
+
)
|
|
20
|
+
|
|
13
21
|
DEFAULT = {"MAX_EDGES": 100,
|
|
14
22
|
"MAX_NODES": 30,
|
|
15
23
|
"MIN_NODE_SIZE": 100,
|
|
16
24
|
"MAX_NODE_SIZE": 2000,
|
|
17
25
|
"MAX_EDGE_WIDTH": 10,
|
|
18
26
|
"GRAPH_SCALE": 2,
|
|
19
|
-
"MAX_FONT_SIZE":
|
|
27
|
+
"MAX_FONT_SIZE": 20,
|
|
20
28
|
"MIN_FONT_SIZE": 8
|
|
21
29
|
}
|
|
22
30
|
|
|
@@ -25,7 +33,7 @@ def softmax(x):
|
|
|
25
33
|
return (np.exp(x - np.max(x)) / np.exp(x - np.max(x)).sum())
|
|
26
34
|
|
|
27
35
|
|
|
28
|
-
def scale_weights(weights, scale_min=0,scale_max=1):
|
|
36
|
+
def scale_weights(weights, scale_min=0, scale_max=1):
|
|
29
37
|
deciles = np.percentile(weights, [10, 20, 30, 40, 50, 60, 70, 80, 90])
|
|
30
38
|
outs = np.searchsorted(deciles, weights)
|
|
31
39
|
return [out * (scale_max-scale_min)/len(deciles)+scale_min for out in outs]
|
|
@@ -160,8 +168,9 @@ class Graph(nx.Graph):
|
|
|
160
168
|
def subgraphX(self, node_list=None, max_edges: int = DEFAULT["MAX_EDGES"]):
|
|
161
169
|
if node_list is None:
|
|
162
170
|
node_list = self.nodes.sort("weight")[:DEFAULT["MAX_NODES"]]
|
|
163
|
-
connected_subgraph_nodes=list(self.find_connected_subgraph())
|
|
164
|
-
node_list = [
|
|
171
|
+
connected_subgraph_nodes = list(self.find_connected_subgraph())
|
|
172
|
+
node_list = [
|
|
173
|
+
node for node in node_list if node in connected_subgraph_nodes]
|
|
165
174
|
|
|
166
175
|
subgraph = nx.subgraph(
|
|
167
176
|
self, nbunch=node_list)
|
|
@@ -169,30 +178,39 @@ class Graph(nx.Graph):
|
|
|
169
178
|
subgraph = subgraph.edge_subgraph(list(edges)[:max_edges])
|
|
170
179
|
return subgraph
|
|
171
180
|
|
|
172
|
-
def plotX(self
|
|
181
|
+
def plotX(self,
|
|
182
|
+
title: str = "Test",
|
|
183
|
+
style: StyleTemplate = NETWORK_STYLE_TEMPLATE,
|
|
184
|
+
ax: Optional[Axes] = None) -> Axes:
|
|
173
185
|
"""
|
|
174
186
|
Plots the degree distribution of the graph, including a degree rank plot and a degree histogram.
|
|
175
187
|
"""
|
|
176
188
|
degree_sequence = sorted([d for n, d in self.degree()], reverse=True)
|
|
177
189
|
dmax = max(degree_sequence)
|
|
178
|
-
|
|
179
|
-
|
|
190
|
+
sns.set_palette(style.palette)
|
|
191
|
+
if ax is None:
|
|
192
|
+
ax = plt.gca()
|
|
180
193
|
|
|
181
194
|
node_sizes, edge_widths, font_sizes = self.layout(
|
|
182
|
-
DEFAULT["
|
|
195
|
+
min_node_size=DEFAULT["MIN_NODE_SIZE"]/5,
|
|
196
|
+
max_node_size=DEFAULT["MAX_NODE_SIZE"],
|
|
197
|
+
max_edge_width=DEFAULT["MAX_EDGE_WIDTH"],
|
|
198
|
+
min_font_size=style.font_mapping.get(0),
|
|
199
|
+
max_font_size=style.font_mapping.get(4))
|
|
183
200
|
pos = nx.spring_layout(self, k=1)
|
|
184
201
|
# nodes
|
|
185
202
|
nx.draw_networkx_nodes(self,
|
|
186
203
|
pos,
|
|
187
204
|
ax=ax,
|
|
188
205
|
node_size=list(node_sizes),
|
|
189
|
-
|
|
190
|
-
cmap=plt.cm.
|
|
206
|
+
node_color=node_sizes,
|
|
207
|
+
cmap=plt.cm.get_cmap(style.palette))
|
|
191
208
|
# edges
|
|
192
209
|
nx.draw_networkx_edges(self,
|
|
193
210
|
pos,
|
|
194
211
|
ax=ax,
|
|
195
|
-
|
|
212
|
+
edge_color=style.font_color,
|
|
213
|
+
edge_cmap=plt.cm.get_cmap(style.palette),
|
|
196
214
|
width=edge_widths)
|
|
197
215
|
# labels
|
|
198
216
|
for font_size, nodes in font_sizes.items():
|
|
@@ -201,16 +219,13 @@ class Graph(nx.Graph):
|
|
|
201
219
|
pos,
|
|
202
220
|
ax=ax,
|
|
203
221
|
font_size=font_size,
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
ax.set_title(
|
|
222
|
+
font_color=style.font_color,
|
|
223
|
+
labels={n: string_formatter(n) for n in nodes})
|
|
224
|
+
ax.set_facecolor(style.background_color)
|
|
225
|
+
ax.set_title(title, color=style.font_color, fontsize=style.font_size*2)
|
|
208
226
|
ax.set_axis_off()
|
|
209
227
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
fig.tight_layout()
|
|
213
|
-
return fig
|
|
228
|
+
return ax
|
|
214
229
|
|
|
215
230
|
def analysis(self, node_list: Optional[List] = None,
|
|
216
231
|
scale: int = DEFAULT["GRAPH_SCALE"],
|
|
@@ -242,12 +257,14 @@ class Graph(nx.Graph):
|
|
|
242
257
|
for node in list(H.nodes):
|
|
243
258
|
if H.degree(node) < 2:
|
|
244
259
|
# Remove the node and its incident edges
|
|
245
|
-
logging.info(
|
|
260
|
+
logging.info(
|
|
261
|
+
f'Removing the {node} node and its incident edges')
|
|
246
262
|
H.remove_node(node)
|
|
247
263
|
removed_node = True
|
|
248
264
|
break
|
|
249
265
|
|
|
250
266
|
return H
|
|
267
|
+
|
|
251
268
|
def top_k_edges(self, attribute: str, reverse: bool = True, k: int = 5) -> Dict[Any, List[Tuple[Any, Dict]]]:
|
|
252
269
|
"""
|
|
253
270
|
Returns the top k edges per node based on the given attribute.
|
|
@@ -275,10 +292,10 @@ class Graph(nx.Graph):
|
|
|
275
292
|
return top_list
|
|
276
293
|
|
|
277
294
|
@staticmethod
|
|
278
|
-
def from_pandas_edgelist(df,
|
|
279
|
-
source:
|
|
280
|
-
target:
|
|
281
|
-
weight:
|
|
295
|
+
def from_pandas_edgelist(df: pd.DataFrame,
|
|
296
|
+
source: str = "source",
|
|
297
|
+
target: str = "target",
|
|
298
|
+
weight: str = "weight"):
|
|
282
299
|
"""
|
|
283
300
|
Initialize netX instance with a simple dataframe
|
|
284
301
|
|
|
@@ -291,7 +308,7 @@ class Graph(nx.Graph):
|
|
|
291
308
|
G = Graph()
|
|
292
309
|
G = nx.from_pandas_edgelist(
|
|
293
310
|
df, source=source, target=target, edge_attr=weight, create_using=G)
|
|
294
|
-
G=G.find_connected_subgraph()
|
|
311
|
+
G = G.find_connected_subgraph()
|
|
295
312
|
|
|
296
313
|
edge_aggregates = G.top_k_edges(attribute=weight, k=10)
|
|
297
314
|
node_aggregates = {}
|
|
@@ -308,11 +325,23 @@ class Graph(nx.Graph):
|
|
|
308
325
|
G = G.edge_subgraph(edges=G.top_k_edges(attribute=weight))
|
|
309
326
|
return G
|
|
310
327
|
|
|
311
|
-
def plot_network(data:pd.DataFrame):
|
|
312
|
-
graph = Graph.from_pandas_edgelist(data)
|
|
313
|
-
graph = graph.subgraphX()
|
|
314
|
-
return graph.analysis()
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
328
|
|
|
329
|
+
def plot_network(pd_df: pd.DataFrame,
|
|
330
|
+
source: str = "source",
|
|
331
|
+
target: str = "target",
|
|
332
|
+
weight: str = "weight",
|
|
333
|
+
title: str = "Test",
|
|
334
|
+
style: StyleTemplate = NETWORK_STYLE_TEMPLATE,
|
|
335
|
+
sort_by: Optional[str] = None,
|
|
336
|
+
ascending: bool = False,
|
|
337
|
+
ax: Optional[Axes] = None) -> Axes:
|
|
338
|
+
|
|
339
|
+
_validate_panda(pd_df, cols=[source, target, weight], sort_by=sort_by)
|
|
340
|
+
|
|
341
|
+
graph = Graph.from_pandas_edgelist(pd_df,
|
|
342
|
+
source=source,
|
|
343
|
+
target=target,
|
|
344
|
+
weight=weight)
|
|
345
|
+
return graph.plotX(title=title,
|
|
346
|
+
style=style,
|
|
347
|
+
ax=ax)
|