d3graph 2.6.2__tar.gz → 2.7.2__tar.gz
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.
- {d3graph-2.6.2/d3graph.egg-info → d3graph-2.7.2}/PKG-INFO +2 -2
- {d3graph-2.6.2 → d3graph-2.7.2}/d3graph/__init__.py +5 -4
- {d3graph-2.6.2 → d3graph-2.7.2}/d3graph/d3graph.py +131 -64
- d3graph-2.7.2/d3graph/d3js/d3graphscript.js +361 -0
- {d3graph-2.6.2 → d3graph-2.7.2}/d3graph/d3js/index.html.j2 +2 -0
- {d3graph-2.6.2 → d3graph-2.7.2}/d3graph/d3js/style.css +6 -0
- {d3graph-2.6.2 → d3graph-2.7.2}/d3graph/examples.py +158 -14
- {d3graph-2.6.2 → d3graph-2.7.2/d3graph.egg-info}/PKG-INFO +2 -2
- {d3graph-2.6.2 → d3graph-2.7.2}/d3graph.egg-info/SOURCES.txt +1 -2
- {d3graph-2.6.2 → d3graph-2.7.2}/d3graph.egg-info/requires.txt +1 -1
- {d3graph-2.6.2 → d3graph-2.7.2}/pyproject.toml +1 -1
- d3graph-2.6.2/d3graph/d3js/d3graphscript.js +0 -339
- d3graph-2.6.2/tests/test_d3graph.py +0 -39
- {d3graph-2.6.2 → d3graph-2.7.2}/LICENSE +0 -0
- {d3graph-2.6.2 → d3graph-2.7.2}/MANIFEST.in +0 -0
- {d3graph-2.6.2 → d3graph-2.7.2}/README.md +0 -0
- {d3graph-2.6.2 → d3graph-2.7.2}/d3graph/d3js/d3.v3.js +0 -0
- {d3graph-2.6.2 → d3graph-2.7.2}/d3graph/examples_docs.py +0 -0
- {d3graph-2.6.2 → d3graph-2.7.2}/d3graph.egg-info/dependency_links.txt +0 -0
- {d3graph-2.6.2 → d3graph-2.7.2}/d3graph.egg-info/top_level.txt +0 -0
- {d3graph-2.6.2 → d3graph-2.7.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: d3graph
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.7.2
|
|
4
4
|
Summary: Python package to create interactive network based on d3js.
|
|
5
5
|
Author-email: Erdogan Taskesen <erdogant@gmail.com>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -24,7 +24,7 @@ Requires-Dist: networkx>2
|
|
|
24
24
|
Requires-Dist: ismember
|
|
25
25
|
Requires-Dist: jinja2
|
|
26
26
|
Requires-Dist: packaging
|
|
27
|
-
Requires-Dist: markupsafe
|
|
27
|
+
Requires-Dist: markupsafe
|
|
28
28
|
Requires-Dist: python-louvain
|
|
29
29
|
Requires-Dist: datazets
|
|
30
30
|
Dynamic: license-file
|
|
@@ -11,11 +11,13 @@ from d3graph.d3graph import (
|
|
|
11
11
|
adjmat2dict,
|
|
12
12
|
data_checks,
|
|
13
13
|
check_logger,
|
|
14
|
+
get_hex_color,
|
|
15
|
+
import_example,
|
|
14
16
|
)
|
|
15
17
|
|
|
16
18
|
__author__ = 'Erdogan Tasksen'
|
|
17
19
|
__email__ = 'erdogant@gmail.com'
|
|
18
|
-
__version__ = '2.
|
|
20
|
+
__version__ = '2.7.2'
|
|
19
21
|
|
|
20
22
|
# Setup root logger
|
|
21
23
|
_logger = logging.getLogger('d3graph')
|
|
@@ -39,13 +41,13 @@ The ouput is a html file that is interactive and stand alone.
|
|
|
39
41
|
|
|
40
42
|
Examples
|
|
41
43
|
--------
|
|
42
|
-
>>> from d3graph import d3graph, vec2adjmat
|
|
44
|
+
>>> from d3graph import d3graph, vec2adjmat, import_example
|
|
43
45
|
>>>
|
|
44
46
|
>>> # Initialize
|
|
45
47
|
>>> d3 = d3graph()
|
|
46
48
|
>>>
|
|
47
49
|
>>> # Load karate example
|
|
48
|
-
>>> df =
|
|
50
|
+
>>> df = import_example('energy')
|
|
49
51
|
>>> adjmat = vec2adjmat(source=df['source'], target=df['target'], weight=df['weight'])
|
|
50
52
|
>>>
|
|
51
53
|
>>> # Initialize
|
|
@@ -63,7 +65,6 @@ Examples
|
|
|
63
65
|
References
|
|
64
66
|
----------
|
|
65
67
|
* D3Graph: erdogant.medium.com
|
|
66
|
-
* D3Blocks: https://medium.com/data-science-collective/d3blocks-the-python-library-to-create-interactive-standalone-and-beautiful-d3-js-charts-ef8c65286e86
|
|
67
68
|
* Github : https://github.com/erdogant/d3graph
|
|
68
69
|
* Documentation: https://erdogant.github.io/d3graph/
|
|
69
70
|
|
|
@@ -12,7 +12,7 @@ import webbrowser
|
|
|
12
12
|
from json import dumps
|
|
13
13
|
from pathlib import Path
|
|
14
14
|
from sys import platform
|
|
15
|
-
from tempfile import
|
|
15
|
+
from tempfile import gettempdir
|
|
16
16
|
from unicodedata import normalize
|
|
17
17
|
import uuid
|
|
18
18
|
|
|
@@ -21,15 +21,13 @@ import colourmap as cm
|
|
|
21
21
|
import networkx as nx
|
|
22
22
|
import numpy as np
|
|
23
23
|
import pandas as pd
|
|
24
|
+
from pandas.arrays import StringArray
|
|
24
25
|
from ismember import ismember
|
|
25
26
|
from jinja2 import Environment, PackageLoader
|
|
26
27
|
from packaging import version
|
|
27
28
|
import datazets as dz
|
|
28
29
|
|
|
29
30
|
logger = logging.getLogger(__name__)
|
|
30
|
-
if not logger.hasHandlers():
|
|
31
|
-
logging.basicConfig(level=logging.INFO, format='[{asctime}] [{name}] [{levelname}] {msg}', style='{', datefmt='%d-%m-%Y %H:%M:%S')
|
|
32
|
-
|
|
33
31
|
|
|
34
32
|
# %%
|
|
35
33
|
class d3graph:
|
|
@@ -58,8 +56,7 @@ class d3graph:
|
|
|
58
56
|
|
|
59
57
|
References
|
|
60
58
|
----------
|
|
61
|
-
*
|
|
62
|
-
* D3Blocks: https://medium.com/data-science-collective/d3blocks-the-python-library-to-create-interactive-standalone-and-beautiful-d3-js-charts-ef8c65286e86
|
|
59
|
+
* Medium: https://erdogant.medium.com/
|
|
63
60
|
* Github : https://github.com/erdogant/d3graph
|
|
64
61
|
* Documentation: https://erdogant.github.io/d3graph/
|
|
65
62
|
|
|
@@ -70,8 +67,17 @@ class d3graph:
|
|
|
70
67
|
charge: int = 600,
|
|
71
68
|
slider=None,
|
|
72
69
|
support: str = 'text',
|
|
70
|
+
link_tension: float = 1,
|
|
71
|
+
sticky: bool = True,
|
|
73
72
|
verbose: int = 20) -> None:
|
|
74
|
-
"""Initialize d3graph.
|
|
73
|
+
"""Initialize d3graph.
|
|
74
|
+
|
|
75
|
+
Parameters (additional to existing)
|
|
76
|
+
------------------------------------
|
|
77
|
+
sticky : bool, (default: False)
|
|
78
|
+
When True, nodes stay fixed in place after being dragged.
|
|
79
|
+
Right-click a fixed node to release it back into the simulation.
|
|
80
|
+
"""
|
|
75
81
|
if slider is None: slider = [None, None]
|
|
76
82
|
# Cleaning
|
|
77
83
|
self._clean()
|
|
@@ -85,6 +91,8 @@ class d3graph:
|
|
|
85
91
|
self.config['charge'] = -abs(charge)
|
|
86
92
|
self.config['slider'] = slider
|
|
87
93
|
self.config['support'] = get_support(support)
|
|
94
|
+
self.config['link_tension'] = link_tension
|
|
95
|
+
self.config['sticky'] = sticky
|
|
88
96
|
# Set paths
|
|
89
97
|
self.config['curpath'] = os.path.dirname(os.path.abspath(__file__))
|
|
90
98
|
self.config['d3_library'] = os.path.abspath(os.path.join(self.config['curpath'], 'd3js/d3.v3.js'))
|
|
@@ -110,6 +118,8 @@ class d3graph:
|
|
|
110
118
|
dark_mode = False,
|
|
111
119
|
notebook: bool = False,
|
|
112
120
|
save_button: bool = True,
|
|
121
|
+
link_tension: float = None,
|
|
122
|
+
sticky: bool = None,
|
|
113
123
|
) -> None:
|
|
114
124
|
"""Build and show the graph.
|
|
115
125
|
|
|
@@ -150,6 +160,11 @@ class d3graph:
|
|
|
150
160
|
save_button : bool, (default: True)
|
|
151
161
|
True: Save button is shown in the HTML to save the image in svg.
|
|
152
162
|
False: No save button is shown in the HTML.
|
|
163
|
+
sticky : bool, (default: None)
|
|
164
|
+
When True, nodes stay fixed in place after being dragged (overrides the value set in __init__).
|
|
165
|
+
When False, nodes are released after dragging (default simulation behaviour).
|
|
166
|
+
When None, the value set in __init__ is used.
|
|
167
|
+
Right-click a fixed node to release it back into the simulation.
|
|
153
168
|
|
|
154
169
|
Returns
|
|
155
170
|
-------
|
|
@@ -171,8 +186,15 @@ class d3graph:
|
|
|
171
186
|
self.config['save_button'] = save_button
|
|
172
187
|
self.config['background_color'] = background_color
|
|
173
188
|
self.config['dark_mode'] = dark_mode
|
|
189
|
+
# Allow show() to override the link_tension set at __init__ time
|
|
190
|
+
if link_tension is not None:
|
|
191
|
+
self.config['link_tension'] = link_tension
|
|
192
|
+
# Override sticky only when explicitly passed
|
|
193
|
+
if sticky is not None:
|
|
194
|
+
self.config['sticky'] = sticky
|
|
174
195
|
# if self.config.get('filepath', None) != 'd3graph.html':
|
|
175
|
-
self.config
|
|
196
|
+
if filepath is not None or self.config.get('filepath') is None:
|
|
197
|
+
self.set_path(filepath)
|
|
176
198
|
|
|
177
199
|
# Create dataframe from co-occurrence matrix
|
|
178
200
|
self.G = make_graph(self.node_properties, self.edge_properties)
|
|
@@ -308,6 +330,10 @@ class d3graph:
|
|
|
308
330
|
self.config['label'] = label
|
|
309
331
|
self.config['label_color'] = label_color
|
|
310
332
|
self.config['label_fontsize'] = label_fontsize
|
|
333
|
+
|
|
334
|
+
if not hasattr(self, 'adjmat'):
|
|
335
|
+
logger.error('adjmat is missing. Initialize first with d3 = d3graph(adjmat)')
|
|
336
|
+
return
|
|
311
337
|
|
|
312
338
|
if (not directed) and (marker_end is not None) or (marker_start is not None):
|
|
313
339
|
logger.info('Set directed=True to see the markers!')
|
|
@@ -447,18 +473,22 @@ class d3graph:
|
|
|
447
473
|
'edge_color': edge_color of the node
|
|
448
474
|
|
|
449
475
|
"""
|
|
476
|
+
if not hasattr(self, 'adjmat'):
|
|
477
|
+
logger.error('adjmat is missing. Initialize first with d3 = d3graph(adjmat)')
|
|
478
|
+
return
|
|
479
|
+
|
|
450
480
|
if minmax is None: minmax = [8, 13]
|
|
451
481
|
node_names = self.adjmat.columns.astype(str)
|
|
452
482
|
nodecount = self.adjmat.shape[0]
|
|
453
483
|
group = np.zeros_like(node_names).astype(int)
|
|
454
484
|
# Check validity of color.
|
|
455
|
-
_check_hex_color(color, nodecount)
|
|
485
|
+
color = _check_hex_color(color, nodecount, cmap=cmap)
|
|
456
486
|
# Store in config
|
|
457
487
|
self.config['cmap'] = 'Paired' if cmap is None else cmap
|
|
458
488
|
self.config['node_scaler'] = scaler
|
|
459
489
|
|
|
460
490
|
# ############ Set node label #############
|
|
461
|
-
if isinstance(label, list):
|
|
491
|
+
if isinstance(label, (list, np.ndarray, pd.Series, pd.Series, StringArray)):
|
|
462
492
|
label = np.array(label).astype(str)
|
|
463
493
|
elif 'numpy' in str(type(label)):
|
|
464
494
|
pass
|
|
@@ -471,7 +501,7 @@ class d3graph:
|
|
|
471
501
|
if len(label) != nodecount: raise ValueError("[label] must be of same length as the number of nodes")
|
|
472
502
|
|
|
473
503
|
# ############ tooltip text #############
|
|
474
|
-
if isinstance(tooltip, list):
|
|
504
|
+
if isinstance(tooltip, (list, np.ndarray, pd.Series, StringArray)):
|
|
475
505
|
tooltip = np.array(tooltip).astype(str)
|
|
476
506
|
elif 'numpy' in str(type(tooltip)):
|
|
477
507
|
pass
|
|
@@ -484,7 +514,7 @@ class d3graph:
|
|
|
484
514
|
if len(tooltip) != nodecount: raise ValueError("[tooltip text] must be of same length as the number of nodes")
|
|
485
515
|
|
|
486
516
|
# ############ Set node color #############
|
|
487
|
-
if isinstance(color, list) and len(color) == nodecount:
|
|
517
|
+
if isinstance(color, (list, np.ndarray, pd.Series, StringArray)) and len(color) == nodecount:
|
|
488
518
|
color = np.array(color)
|
|
489
519
|
elif 'numpy' in str(type(color)):
|
|
490
520
|
color = _get_hexcolor(color, cmap=self.config['cmap'])
|
|
@@ -514,7 +544,7 @@ class d3graph:
|
|
|
514
544
|
fontsize = _set_node_fontsize(self, fontsize, nodecount)
|
|
515
545
|
|
|
516
546
|
# ########## Set node color edge #############
|
|
517
|
-
if isinstance(edge_color, list):
|
|
547
|
+
if isinstance(edge_color, (list, np.ndarray, pd.Series, StringArray)):
|
|
518
548
|
edge_color = np.array(edge_color)
|
|
519
549
|
elif 'numpy' in str(type(edge_color)):
|
|
520
550
|
pass
|
|
@@ -546,7 +576,7 @@ class d3graph:
|
|
|
546
576
|
marker = _set_marker(self, marker, nodecount)
|
|
547
577
|
|
|
548
578
|
# ############ Set node edge size #############
|
|
549
|
-
if isinstance(edge_size, list):
|
|
579
|
+
if isinstance(edge_size, (list, np.ndarray, pd.Series, StringArray)):
|
|
550
580
|
edge_size = np.array(edge_size)
|
|
551
581
|
elif 'numpy' in str(type(edge_size)):
|
|
552
582
|
pass
|
|
@@ -569,16 +599,16 @@ class d3graph:
|
|
|
569
599
|
'marker': marker[i],
|
|
570
600
|
'label': label[i],
|
|
571
601
|
'tooltip': tooltip[i],
|
|
572
|
-
'color': color[i]
|
|
573
|
-
'opacity': opacity[i]
|
|
574
|
-
'fontcolor': fontcolor[i]
|
|
575
|
-
'fontsize': fontsize[i]
|
|
602
|
+
'color': str(color[i]),
|
|
603
|
+
'opacity': str(opacity[i]),
|
|
604
|
+
'fontcolor': str(fontcolor[i]),
|
|
605
|
+
'fontsize': str(fontsize[i]),
|
|
576
606
|
'size': size[i],
|
|
577
607
|
'edge_size': edge_size[i],
|
|
578
608
|
'edge_color': edge_color[i],
|
|
579
609
|
'group': group[i]}
|
|
580
610
|
|
|
581
|
-
logger.info('Number of unique nodes:
|
|
611
|
+
logger.info(f'Number of unique nodes: {len(self.node_properties.keys())}')
|
|
582
612
|
|
|
583
613
|
# compute clusters
|
|
584
614
|
def get_cluster_color(self, node_names: list = None, color: str = '#000080') -> tuple:
|
|
@@ -685,13 +715,13 @@ class d3graph:
|
|
|
685
715
|
|
|
686
716
|
Examples
|
|
687
717
|
--------
|
|
688
|
-
>>> from d3graph import d3graph
|
|
718
|
+
>>> from d3graph import d3graph, import_example
|
|
689
719
|
>>>
|
|
690
720
|
>>> # Initialize
|
|
691
721
|
>>> d3 = d3graph()
|
|
692
722
|
>>>
|
|
693
723
|
>>> # Load karate example
|
|
694
|
-
>>> adjmat, df =
|
|
724
|
+
>>> adjmat, df = import_example('karate')
|
|
695
725
|
>>>
|
|
696
726
|
>>> # Initialize
|
|
697
727
|
>>> d3.graph(adjmat)
|
|
@@ -763,6 +793,8 @@ class d3graph:
|
|
|
763
793
|
'max_slider': self.config['slider'][1],
|
|
764
794
|
'directed': self.config['directed'],
|
|
765
795
|
'collision': self.config['collision'],
|
|
796
|
+
'link_tension': self.config.get('link_tension', 1.0),
|
|
797
|
+
'sticky': self.config.get('sticky', False),
|
|
766
798
|
'CLICK_COMMENT': CLICK_COMMENT,
|
|
767
799
|
'CLICK_FILL': click_properties['fill'],
|
|
768
800
|
'CLICK_STROKE': click_properties['stroke'],
|
|
@@ -833,7 +865,8 @@ class d3graph:
|
|
|
833
865
|
os.makedirs(dirname, exist_ok=True)
|
|
834
866
|
filepath = os.path.abspath(os.path.join(dirname, filename))
|
|
835
867
|
logger.debug(f'filepath is set to [{filepath}]')
|
|
836
|
-
|
|
868
|
+
# Set to config
|
|
869
|
+
self.config['filepath'] = Path(filepath)
|
|
837
870
|
|
|
838
871
|
def import_example(self, data='energy', url=None, sep=','):
|
|
839
872
|
"""Import example dataset from github source.
|
|
@@ -857,38 +890,7 @@ class d3graph:
|
|
|
857
890
|
* https://github.com/erdogant/datazets
|
|
858
891
|
|
|
859
892
|
"""
|
|
860
|
-
|
|
861
|
-
source = ['node A', 'node F', 'node B', 'node B', 'node B', 'node A', 'node C', 'node Z']
|
|
862
|
-
target = ['node F', 'node B', 'node J', 'node F', 'node F', 'node M', 'node M', 'node A']
|
|
863
|
-
weight = [5.56, 0.5, 0.64, 0.23, 0.9, 3.28, 0.5, 0.45]
|
|
864
|
-
adjmat = vec2adjmat(source, target, weight=weight)
|
|
865
|
-
return adjmat, None
|
|
866
|
-
elif data == 'bigbang':
|
|
867
|
-
df = dz.get(data=data)
|
|
868
|
-
adjmat = vec2adjmat(df['source'], df['target'], weight=df['weight'])
|
|
869
|
-
return adjmat
|
|
870
|
-
elif data == 'karate':
|
|
871
|
-
import scipy
|
|
872
|
-
if version.parse(scipy.__version__) < version.parse('1.8.0'):
|
|
873
|
-
raise ImportError(
|
|
874
|
-
'[d3graph] >Error: This release requires scipy version >= 1.8.0. Try: pip install -U scipy>=1.8.0')
|
|
875
|
-
|
|
876
|
-
G = nx.karate_club_graph()
|
|
877
|
-
adjmat = nx.adjacency_matrix(G).todense()
|
|
878
|
-
adjmat = pd.DataFrame(index=range(adjmat.shape[0]), data=adjmat, columns=range(adjmat.shape[0]))
|
|
879
|
-
adjmat.columns = adjmat.columns.astype(str)
|
|
880
|
-
adjmat.index = adjmat.index.astype(str)
|
|
881
|
-
adjmat.iloc[3, 4] = 5
|
|
882
|
-
adjmat.iloc[4, 5] = 6
|
|
883
|
-
adjmat.iloc[5, 6] = 7
|
|
884
|
-
|
|
885
|
-
df = pd.DataFrame(index=adjmat.index)
|
|
886
|
-
df['degree'] = np.array([*G.degree()])[:, 1]
|
|
887
|
-
df['label'] = [G.nodes[i]['club'] for i in range(len(G.nodes))]
|
|
888
|
-
|
|
889
|
-
return adjmat, df
|
|
890
|
-
else:
|
|
891
|
-
return dz.get(data=data, url=url, sep=sep)
|
|
893
|
+
return import_example(data=data, url=url, sep=sep)
|
|
892
894
|
|
|
893
895
|
|
|
894
896
|
# %%
|
|
@@ -1193,6 +1195,7 @@ def adjmat2dict(adjmat: pd.DataFrame,
|
|
|
1193
1195
|
df['label_color']=label_color
|
|
1194
1196
|
df['label_fontsize']=label_fontsize
|
|
1195
1197
|
df['edge_style']=edge_style
|
|
1198
|
+
df['edge_color']=edge_color
|
|
1196
1199
|
df['edge_opacity'] = edge_opacity
|
|
1197
1200
|
df['tooltip'] = df['weight'].astype(str)
|
|
1198
1201
|
|
|
@@ -1357,6 +1360,7 @@ def _normalize_size(getsizes, minscale=0.5, maxscale=4, scaler: str = 'zscore'):
|
|
|
1357
1360
|
# Instead of Min-Max scaling, that shrinks any distribution in the [0, 1] interval, scaling the variables to
|
|
1358
1361
|
# Z-scores is better. Min-Max Scaling is too sensitive to outlier observations and generates unseen problems.
|
|
1359
1362
|
|
|
1363
|
+
getsizes = getsizes.copy()
|
|
1360
1364
|
# Set sizes to 0 if not available
|
|
1361
1365
|
getsizes[np.isinf(getsizes)]=0
|
|
1362
1366
|
getsizes[np.isnan(getsizes)]=0
|
|
@@ -1395,6 +1399,8 @@ def _get_hexcolor(label, cmap: str = 'Paired'):
|
|
|
1395
1399
|
|
|
1396
1400
|
return label
|
|
1397
1401
|
|
|
1402
|
+
def get_hex_color(labels, cmap='Set1', opaque_type='per_class', gradient=None):
|
|
1403
|
+
return cm.fromlist(labels, scheme='hex', opaque_type=opaque_type, gradient=gradient)
|
|
1398
1404
|
|
|
1399
1405
|
# %% Do checks
|
|
1400
1406
|
def library_compatibility_checks() -> None:
|
|
@@ -1591,15 +1597,21 @@ def adjmat2vec(adjmat, min_weight: float = 1.0) -> pd.DataFrame:
|
|
|
1591
1597
|
return adjmat
|
|
1592
1598
|
|
|
1593
1599
|
|
|
1594
|
-
def _check_hex_color(color, n=None):
|
|
1595
|
-
if isinstance(color, str) and len(color) != 7:
|
|
1596
|
-
'Input parameter [color] has wrong format. Must be like color="#000000"')
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
if (
|
|
1602
|
-
|
|
1600
|
+
def _check_hex_color(color, n=None, cmap='Set1'):
|
|
1601
|
+
if isinstance(color, str) and len(color) != 7:
|
|
1602
|
+
logger.warning('Input parameter [color] has wrong format. Must be like color="#000000" <auto-fixing>')
|
|
1603
|
+
return get_hex_color(color, cmap=cmap)[0]
|
|
1604
|
+
if isinstance(color, (list, np.ndarray, pd.Series, pd.Series, StringArray)) and len(color) == 0:
|
|
1605
|
+
logger.warning('Input parameter [color] has wrong format and length. Must be like: color=["#000000", "...", "#000000"] <auto-fixing>')
|
|
1606
|
+
return get_hex_color(color, cmap=cmap)[0]
|
|
1607
|
+
if isinstance(color, (list, np.ndarray, pd.Series, pd.Series, StringArray)) and (not np.all(list(map(lambda x: len(x) == 7, color)))):
|
|
1608
|
+
logger.warning('[color] contains incorrect hex-colors. Hex must be of length 7: ["#000000", "#000000", etc] <auto-fixing>')
|
|
1609
|
+
return get_hex_color(color, cmap=cmap)[0]
|
|
1610
|
+
if (n is not None) and isinstance(color, (list, np.ndarray, pd.Series, pd.Series, StringArray)) and len(color) != n:
|
|
1611
|
+
logger.warning(f'Input parameter [color] has wrong length. Must be of length: {str(n)} <auto-fixing>')
|
|
1612
|
+
return get_hex_color(color, cmap=cmap)[0]
|
|
1613
|
+
# Return original input
|
|
1614
|
+
return color
|
|
1603
1615
|
|
|
1604
1616
|
|
|
1605
1617
|
def _set_opacity(self, opacity, nodecount, node_names):
|
|
@@ -1723,6 +1735,61 @@ def _set_node_fontcolor(self, fontcolor, color, node_names, nodecount):
|
|
|
1723
1735
|
# return
|
|
1724
1736
|
return fontcolor
|
|
1725
1737
|
|
|
1738
|
+
def import_example(data='energy', url=None, sep=','):
|
|
1739
|
+
"""Import example dataset from github source.
|
|
1740
|
+
|
|
1741
|
+
Import one of the few datasets from github source or specify your own download url link.
|
|
1742
|
+
|
|
1743
|
+
Parameters
|
|
1744
|
+
----------
|
|
1745
|
+
data : str
|
|
1746
|
+
Name of datasets: 'sprinkler', 'titanic', 'student', 'fifa', 'cancer', 'waterpump', 'retail'
|
|
1747
|
+
url : str
|
|
1748
|
+
url link to to dataset.
|
|
1749
|
+
|
|
1750
|
+
Returns
|
|
1751
|
+
-------
|
|
1752
|
+
pd.DataFrame()
|
|
1753
|
+
Dataset containing mixed features.
|
|
1754
|
+
|
|
1755
|
+
References
|
|
1756
|
+
----------
|
|
1757
|
+
* https://github.com/erdogant/datazets
|
|
1758
|
+
|
|
1759
|
+
"""
|
|
1760
|
+
if data == 'small':
|
|
1761
|
+
source = ['node A', 'node F', 'node B', 'node B', 'node B', 'node A', 'node C', 'node Z']
|
|
1762
|
+
target = ['node F', 'node B', 'node J', 'node F', 'node F', 'node M', 'node M', 'node A']
|
|
1763
|
+
weight = [5.56, 0.5, 0.64, 0.23, 0.9, 3.28, 0.5, 0.45]
|
|
1764
|
+
adjmat = vec2adjmat(source, target, weight=weight)
|
|
1765
|
+
return adjmat, None
|
|
1766
|
+
elif data == 'bigbang':
|
|
1767
|
+
df = dz.get(data=data)
|
|
1768
|
+
adjmat = vec2adjmat(df['source'], df['target'], weight=df['weight'])
|
|
1769
|
+
return adjmat
|
|
1770
|
+
elif data == 'karate':
|
|
1771
|
+
import scipy
|
|
1772
|
+
if version.parse(scipy.__version__) < version.parse('1.8.0'):
|
|
1773
|
+
raise ImportError(
|
|
1774
|
+
'[d3graph] >Error: This release requires scipy version >= 1.8.0. Try: pip install -U scipy>=1.8.0')
|
|
1775
|
+
|
|
1776
|
+
G = nx.karate_club_graph()
|
|
1777
|
+
adjmat = nx.adjacency_matrix(G).todense()
|
|
1778
|
+
adjmat = pd.DataFrame(index=range(adjmat.shape[0]), data=adjmat, columns=range(adjmat.shape[0]))
|
|
1779
|
+
adjmat.columns = adjmat.columns.astype(str)
|
|
1780
|
+
adjmat.index = adjmat.index.astype(str)
|
|
1781
|
+
adjmat.iloc[3, 4] = 5
|
|
1782
|
+
adjmat.iloc[4, 5] = 6
|
|
1783
|
+
adjmat.iloc[5, 6] = 7
|
|
1784
|
+
|
|
1785
|
+
df = pd.DataFrame(index=adjmat.index)
|
|
1786
|
+
df['degree'] = np.array([*G.degree()])[:, 1]
|
|
1787
|
+
df['label'] = [G.nodes[i]['club'] for i in range(len(G.nodes))]
|
|
1788
|
+
|
|
1789
|
+
return adjmat, df
|
|
1790
|
+
else:
|
|
1791
|
+
return dz.get(data=data, url=url, sep=sep)
|
|
1792
|
+
|
|
1726
1793
|
|
|
1727
1794
|
def get_support(support):
|
|
1728
1795
|
"""Support."""
|
|
@@ -1734,4 +1801,4 @@ def get_support(support):
|
|
|
1734
1801
|
script = script + '\n' + "<div data-ea-publisher='erdogantgithubio' data-ea-type='{TYPE}' data-ea-style='stickybox'></div>".replace('{TYPE}', support)
|
|
1735
1802
|
|
|
1736
1803
|
# Return
|
|
1737
|
-
return script
|
|
1804
|
+
return script
|