hvplot 0.9.3a1__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.
- hvplot/__init__.py +322 -0
- hvplot/_version.py +16 -0
- hvplot/backend_transforms.py +329 -0
- hvplot/converter.py +2855 -0
- hvplot/cudf.py +26 -0
- hvplot/dask.py +42 -0
- hvplot/data/crime.csv +56 -0
- hvplot/datasets.yaml +48 -0
- hvplot/fugue.py +64 -0
- hvplot/ibis.py +21 -0
- hvplot/intake.py +32 -0
- hvplot/interactive.py +968 -0
- hvplot/networkx.py +625 -0
- hvplot/pandas.py +30 -0
- hvplot/plotting/__init__.py +63 -0
- hvplot/plotting/andrews_curves.py +99 -0
- hvplot/plotting/core.py +2288 -0
- hvplot/plotting/lag_plot.py +34 -0
- hvplot/plotting/parallel_coordinates.py +85 -0
- hvplot/plotting/scatter_matrix.py +220 -0
- hvplot/polars.py +21 -0
- hvplot/sample_data.py +30 -0
- hvplot/streamz.py +21 -0
- hvplot/tests/__init__.py +0 -0
- hvplot/tests/conftest.py +44 -0
- hvplot/tests/data/README.md +5 -0
- hvplot/tests/data/RGB-red.byte.tif +0 -0
- hvplot/tests/plotting/__init__.py +0 -0
- hvplot/tests/plotting/testcore.py +108 -0
- hvplot/tests/plotting/testohlc.py +34 -0
- hvplot/tests/plotting/testscattermatrix.py +138 -0
- hvplot/tests/test_links.py +99 -0
- hvplot/tests/testbackend_transforms.py +89 -0
- hvplot/tests/testcharts.py +452 -0
- hvplot/tests/testfugue.py +46 -0
- hvplot/tests/testgeo.py +468 -0
- hvplot/tests/testgeowithoutgv.py +60 -0
- hvplot/tests/testgridplots.py +259 -0
- hvplot/tests/testhelp.py +75 -0
- hvplot/tests/testibis.py +17 -0
- hvplot/tests/testinteractive.py +1442 -0
- hvplot/tests/testnetworkx.py +26 -0
- hvplot/tests/testoperations.py +385 -0
- hvplot/tests/testoptions.py +596 -0
- hvplot/tests/testoverrides.py +74 -0
- hvplot/tests/testpanel.py +70 -0
- hvplot/tests/testpatch.py +135 -0
- hvplot/tests/testplotting.py +69 -0
- hvplot/tests/teststreaming.py +28 -0
- hvplot/tests/testtransforms.py +39 -0
- hvplot/tests/testui.py +383 -0
- hvplot/tests/testutil.py +378 -0
- hvplot/tests/util.py +82 -0
- hvplot/ui.py +1032 -0
- hvplot/util.py +677 -0
- hvplot/utilities.py +129 -0
- hvplot/xarray.py +62 -0
- hvplot-0.9.3a1.dist-info/LICENSE +29 -0
- hvplot-0.9.3a1.dist-info/METADATA +243 -0
- hvplot-0.9.3a1.dist-info/RECORD +63 -0
- hvplot-0.9.3a1.dist-info/WHEEL +5 -0
- hvplot-0.9.3a1.dist-info/entry_points.txt +2 -0
- hvplot-0.9.3a1.dist-info/top_level.txt +1 -0
hvplot/networkx.py
ADDED
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
from collections import defaultdict
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import networkx as nx
|
|
5
|
+
import holoviews as _hv
|
|
6
|
+
|
|
7
|
+
from bokeh.models import HoverTool
|
|
8
|
+
from holoviews import Graph, Labels, dim
|
|
9
|
+
from holoviews.core.options import Store
|
|
10
|
+
from holoviews.core.util import dimension_sanitizer
|
|
11
|
+
from holoviews.plotting.bokeh import GraphPlot, LabelsPlot
|
|
12
|
+
from holoviews.plotting.bokeh.styles import markers
|
|
13
|
+
|
|
14
|
+
from .backend_transforms import _transfer_opts_cur_backend
|
|
15
|
+
from .util import process_crs
|
|
16
|
+
from .utilities import save, show # noqa
|
|
17
|
+
|
|
18
|
+
if _hv.extension and not getattr(_hv.extension, '_loaded', False):
|
|
19
|
+
_hv.extension('bokeh', logo=False)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _from_networkx(G, positions, nodes=None, cls=Graph, **kwargs):
|
|
23
|
+
"""
|
|
24
|
+
Generate a Graph element from a networkx.Graph object and networkx
|
|
25
|
+
layout function or dictionary of node positions. Any keyword
|
|
26
|
+
arguments will be passed to the layout function. By default it
|
|
27
|
+
will extract all node and edge attributes from the networkx.Graph
|
|
28
|
+
but explicit node information may also be supplied. Any non-scalar
|
|
29
|
+
attributes, such as lists or dictionaries will be ignored.
|
|
30
|
+
|
|
31
|
+
Parameters
|
|
32
|
+
----------
|
|
33
|
+
G : networkx.Graph
|
|
34
|
+
Graph to convert to Graph element
|
|
35
|
+
positions : dict or callable
|
|
36
|
+
Node positions defined as a dictionary mapping from node id to
|
|
37
|
+
(x, y) tuple or networkx layout function which computes a
|
|
38
|
+
positions dictionary.
|
|
39
|
+
kwargs : dict
|
|
40
|
+
Keyword arguments for the element
|
|
41
|
+
|
|
42
|
+
Returns
|
|
43
|
+
-------
|
|
44
|
+
graph : holoviews.Graph
|
|
45
|
+
Graph element
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
# Unpack edges
|
|
49
|
+
edges = defaultdict(list)
|
|
50
|
+
for start, end in G.edges():
|
|
51
|
+
for attr, value in sorted(G.adj[start][end].items()):
|
|
52
|
+
if isinstance(value, (list, dict)):
|
|
53
|
+
continue # Cannot handle list or dict attrs
|
|
54
|
+
edges[attr].append(value)
|
|
55
|
+
|
|
56
|
+
# Handle tuple node indexes (used in 2D grid Graphs)
|
|
57
|
+
if isinstance(start, tuple):
|
|
58
|
+
start = str(start)
|
|
59
|
+
if isinstance(end, tuple):
|
|
60
|
+
end = str(end)
|
|
61
|
+
edges['start'].append(start)
|
|
62
|
+
edges['end'].append(end)
|
|
63
|
+
edge_cols = sorted(
|
|
64
|
+
k for k in edges if k not in ('start', 'end') and len(edges[k]) == len(edges['start'])
|
|
65
|
+
)
|
|
66
|
+
edge_vdims = [str(col) if isinstance(col, int) else col for col in edge_cols]
|
|
67
|
+
edge_data = tuple(edges[col] for col in ['start', 'end'] + edge_cols)
|
|
68
|
+
|
|
69
|
+
# Unpack user node info
|
|
70
|
+
xdim, ydim, idim = cls.node_type.kdims[:3]
|
|
71
|
+
if nodes:
|
|
72
|
+
node_columns = nodes.columns()
|
|
73
|
+
idx_dim = nodes.kdims[0].name
|
|
74
|
+
info_cols, values = zip(*((k, v) for k, v in node_columns.items() if k != idx_dim))
|
|
75
|
+
node_info = {i: vals for i, vals in zip(node_columns[idx_dim], zip(*values))}
|
|
76
|
+
else:
|
|
77
|
+
info_cols = []
|
|
78
|
+
node_info = None
|
|
79
|
+
node_columns = defaultdict(list)
|
|
80
|
+
|
|
81
|
+
# Unpack node positions
|
|
82
|
+
for idx, pos in positions.items():
|
|
83
|
+
node = G.nodes.get(idx)
|
|
84
|
+
if node is None:
|
|
85
|
+
continue
|
|
86
|
+
x, y = pos
|
|
87
|
+
node_columns[xdim.name].append(x)
|
|
88
|
+
node_columns[ydim.name].append(y)
|
|
89
|
+
for attr, value in node.items():
|
|
90
|
+
if isinstance(value, (list, dict, tuple)):
|
|
91
|
+
continue
|
|
92
|
+
node_columns[attr].append(value)
|
|
93
|
+
for i, col in enumerate(info_cols):
|
|
94
|
+
node_columns[col].append(node_info[idx][i])
|
|
95
|
+
if isinstance(idx, tuple):
|
|
96
|
+
idx = str(idx) # Tuple node indexes handled as strings
|
|
97
|
+
node_columns[idim.name].append(idx)
|
|
98
|
+
node_cols = sorted(
|
|
99
|
+
k
|
|
100
|
+
for k in node_columns
|
|
101
|
+
if k not in cls.node_type.kdims and len(node_columns[k]) == len(node_columns[xdim.name])
|
|
102
|
+
)
|
|
103
|
+
columns = [xdim.name, ydim.name, idim.name] + node_cols + list(info_cols)
|
|
104
|
+
node_data = tuple(node_columns[col] for col in columns)
|
|
105
|
+
|
|
106
|
+
# Construct nodes
|
|
107
|
+
vdims = []
|
|
108
|
+
for col in node_cols:
|
|
109
|
+
if isinstance(col, int):
|
|
110
|
+
dim = str(col)
|
|
111
|
+
elif nodes is not None and col in nodes.vdims:
|
|
112
|
+
dim = nodes.get_dimension(col)
|
|
113
|
+
else:
|
|
114
|
+
dim = col
|
|
115
|
+
vdims.append(dim)
|
|
116
|
+
nodes = cls.node_type(node_data, vdims=vdims)
|
|
117
|
+
|
|
118
|
+
# Construct graph
|
|
119
|
+
return cls((edge_data, nodes), vdims=edge_vdims)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def draw(G, pos=None, **kwargs):
|
|
123
|
+
"""
|
|
124
|
+
Draw the graph G using hvPlot.
|
|
125
|
+
|
|
126
|
+
Draw the graph with hvPlot with options for node positions,
|
|
127
|
+
labeling, titles, and many other drawing features.
|
|
128
|
+
|
|
129
|
+
Parameters
|
|
130
|
+
----------
|
|
131
|
+
G : graph
|
|
132
|
+
A networkx graph
|
|
133
|
+
pos : dictionary, optional
|
|
134
|
+
A dictionary with nodes as keys and positions as values.
|
|
135
|
+
If not specified a spring layout positioning will be computed.
|
|
136
|
+
See :py:mod:`networkx.drawing.layout` for functions that
|
|
137
|
+
compute node positions.
|
|
138
|
+
arrows : bool, optional (default=True)
|
|
139
|
+
For directed graphs, if True draw arrowheads.
|
|
140
|
+
Note: Arrows will be the same color as edges.
|
|
141
|
+
arrowhead_length : float, optional (default=0.025)
|
|
142
|
+
The length of the arrows as fraction of the overall extent of
|
|
143
|
+
the graph
|
|
144
|
+
with_labels : bool, optional (default=True)
|
|
145
|
+
Set to True to draw labels on the nodes.
|
|
146
|
+
nodelist : list, optional (default G.nodes())
|
|
147
|
+
Draw only specified nodes
|
|
148
|
+
edgelist : list, optional (default=G.edges())
|
|
149
|
+
Draw only specified edges
|
|
150
|
+
node_size : scalar or array, optional (default=300)
|
|
151
|
+
Size of nodes. If an array is specified it must be the
|
|
152
|
+
same length as nodelist.
|
|
153
|
+
node_color : color string, node attribute, or array of floats, (default='r')
|
|
154
|
+
Can be a single color, the name of an attribute on the nodes or
|
|
155
|
+
sequence of colors with the same length as nodelist. If the
|
|
156
|
+
node_color references an attribute on the nodes or is a list of
|
|
157
|
+
values they will be colormapped using the cmap and vmin, vmax
|
|
158
|
+
parameters.
|
|
159
|
+
node_shape : string, optional (default='o')
|
|
160
|
+
The shape of the node. Specification is as valid bokeh marker.
|
|
161
|
+
alpha : float, optional (default=1.0)
|
|
162
|
+
The node and edge transparency
|
|
163
|
+
cmap : Colormap, optional (default=None)
|
|
164
|
+
Colormap for mapping intensities of nodes
|
|
165
|
+
vmin,vmax : float, optional (default=None)
|
|
166
|
+
Minimum and maximum for node colormap scaling
|
|
167
|
+
linewidths : [None | scalar | sequence]
|
|
168
|
+
Line width of symbol border (default =1.0)
|
|
169
|
+
edge_width : float, optional (default=1.0)
|
|
170
|
+
Line width of edges
|
|
171
|
+
edge_color : color string, or array of floats (default='r')
|
|
172
|
+
Can be a single color, the name of an attribute on the edges or
|
|
173
|
+
sequence of colors with the same length as the edges. If the
|
|
174
|
+
edge_color references an attribute on the edges or is a list of
|
|
175
|
+
values they will be colormapped using the edge_cmap and
|
|
176
|
+
edge_vmin, edge_vmax parameters.
|
|
177
|
+
edge_cmap : Matplotlib colormap, optional (default=None)
|
|
178
|
+
Colormap for mapping intensities of edges
|
|
179
|
+
edge_vmin,edge_vmax : floats, optional (default=None)
|
|
180
|
+
Minimum and maximum for edge colormap scaling
|
|
181
|
+
style : string, optional (default='solid')
|
|
182
|
+
Edge line style (solid|dashed|dotted,dashdot)
|
|
183
|
+
labels : dictionary or string, optional (default=None)
|
|
184
|
+
Node labels in a dictionary keyed by node of text labels or
|
|
185
|
+
a string referencing a node attribute
|
|
186
|
+
font_size : int, optional (default=12)
|
|
187
|
+
Font size for text labels
|
|
188
|
+
font_color : string, optional (default='black')
|
|
189
|
+
Font color string
|
|
190
|
+
font_family : string, optional (default='sans-serif')
|
|
191
|
+
Font family
|
|
192
|
+
label : string, optional
|
|
193
|
+
Label for graph legend
|
|
194
|
+
selection_policy : string, optional (default='nodes')
|
|
195
|
+
Whether to select 'nodes', 'edges' or None on tap and selection
|
|
196
|
+
events.
|
|
197
|
+
inspection_policy : string, optional (default='nodes')
|
|
198
|
+
Whether to select 'nodes', 'edges' or None on tap and selection
|
|
199
|
+
events.
|
|
200
|
+
geo : boolean, optional (default=False)
|
|
201
|
+
Whether to return a GeoViews graph
|
|
202
|
+
crs : cartopy.crs.CRS
|
|
203
|
+
A cartopy coordinate reference system (enables a geographic plot)
|
|
204
|
+
height : int, optional (default=400)
|
|
205
|
+
The height of the plot in pixels
|
|
206
|
+
width : int, optional (default=400)
|
|
207
|
+
The width of the plot in pixels
|
|
208
|
+
"""
|
|
209
|
+
if pos is None:
|
|
210
|
+
pos = nx.drawing.spring_layout
|
|
211
|
+
|
|
212
|
+
if not isinstance(pos, dict):
|
|
213
|
+
pos = pos(G, **kwargs.get('layout_kwargs', {}))
|
|
214
|
+
|
|
215
|
+
params, label_params = {}, {}
|
|
216
|
+
label_element = Labels
|
|
217
|
+
if kwargs.get('geo', False) or 'crs' in kwargs:
|
|
218
|
+
try:
|
|
219
|
+
import geoviews
|
|
220
|
+
except ImportError:
|
|
221
|
+
raise ImportError(
|
|
222
|
+
'In order to use geo-related features '
|
|
223
|
+
'the geoviews library must be available. '
|
|
224
|
+
'It can be installed with pip or conda.'
|
|
225
|
+
)
|
|
226
|
+
crs = process_crs(kwargs.get('crs'))
|
|
227
|
+
label_element = geoviews.Labels
|
|
228
|
+
params['cls'] = geoviews.Graph
|
|
229
|
+
params['crs'] = crs
|
|
230
|
+
label_params['crs'] = crs
|
|
231
|
+
|
|
232
|
+
# Construct Graph object
|
|
233
|
+
g = _from_networkx(G, pos, **params)
|
|
234
|
+
|
|
235
|
+
if 'nodelist' in kwargs:
|
|
236
|
+
g.nodes.data = g.nodes.data.iloc[list(kwargs['nodelist'])]
|
|
237
|
+
|
|
238
|
+
if 'edgelist' in kwargs:
|
|
239
|
+
edges = g.array([0, 1])
|
|
240
|
+
comparisons = []
|
|
241
|
+
for edge in kwargs['edgelist']:
|
|
242
|
+
comparisons.append(edges == edge)
|
|
243
|
+
if len(comparisons):
|
|
244
|
+
selector = np.logical_and(*np.logical_or.reduce(comparisons).T)
|
|
245
|
+
g = g.iloc[selector]
|
|
246
|
+
else:
|
|
247
|
+
g = g.iloc[:0]
|
|
248
|
+
|
|
249
|
+
# Compute options
|
|
250
|
+
inspection_policy = kwargs.pop('inspection_policy', 'nodes')
|
|
251
|
+
opts = dict(
|
|
252
|
+
axiswise=True,
|
|
253
|
+
arrowhead_length=kwargs.get('arrowhead_length', 0.025),
|
|
254
|
+
directed=kwargs.pop('arrows', isinstance(G, nx.DiGraph)),
|
|
255
|
+
colorbar=kwargs.pop('colorbar', False),
|
|
256
|
+
padding=kwargs.get('padding', 0.1),
|
|
257
|
+
width=kwargs.pop('width', 400),
|
|
258
|
+
height=kwargs.pop('height', 400),
|
|
259
|
+
selection_policy=kwargs.pop('selection_policy', 'nodes'),
|
|
260
|
+
inspection_policy=inspection_policy,
|
|
261
|
+
node_fill_color='red',
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
if '_axis_defaults':
|
|
265
|
+
opts.update(xaxis=None, yaxis=None, show_frame=False)
|
|
266
|
+
|
|
267
|
+
opts.update({k: kwargs.pop(k) for k in list(kwargs) if k in GraphPlot.style_opts})
|
|
268
|
+
if 'node_size' in opts:
|
|
269
|
+
if isinstance(opts['node_size'], str):
|
|
270
|
+
opts['node_size'] = dim(opts['node_size'])
|
|
271
|
+
opts['node_size'] = np.sqrt(opts['node_size'])
|
|
272
|
+
if 'node_color' in opts:
|
|
273
|
+
opts['node_fill_color'] = opts.pop('node_color')
|
|
274
|
+
if 'edge_color' in opts:
|
|
275
|
+
opts['edge_line_color'] = opts.pop('edge_color')
|
|
276
|
+
if 'node_shape' in kwargs:
|
|
277
|
+
marker = kwargs.pop('node_shape')
|
|
278
|
+
if marker in markers:
|
|
279
|
+
marker_opts = markers[marker]
|
|
280
|
+
marker = marker_opts['marker']
|
|
281
|
+
if 'angle' in marker_opts:
|
|
282
|
+
Store.add_style_opts(Graph, ['node_angle'], 'bokeh')
|
|
283
|
+
opts['node_angle'] = marker_opts['angle']
|
|
284
|
+
opts['node_marker'] = marker
|
|
285
|
+
if 'alpha' in kwargs:
|
|
286
|
+
alpha = kwargs.pop('alpha')
|
|
287
|
+
opts['node_alpha'] = alpha
|
|
288
|
+
opts['edge_alpha'] = alpha
|
|
289
|
+
if 'linewidths' in kwargs:
|
|
290
|
+
opts['node_line_width'] = kwargs.pop('linewidths')
|
|
291
|
+
if 'edge_width' in kwargs:
|
|
292
|
+
opts['edge_line_width'] = kwargs.pop('edge_width')
|
|
293
|
+
if 'style' in kwargs:
|
|
294
|
+
opts['edge_line_dash'] = kwargs.pop('style')
|
|
295
|
+
|
|
296
|
+
node_styles = ('node_fill_color', 'node_size', 'node_alpha', 'node_line_width')
|
|
297
|
+
for node_style in node_styles:
|
|
298
|
+
if isinstance(opts.get(node_style), (np.ndarray, list, range)):
|
|
299
|
+
g = g.clone(
|
|
300
|
+
(
|
|
301
|
+
g.data,
|
|
302
|
+
g.nodes.add_dimension(node_style, len(g.nodes.vdims), opts[node_style], True),
|
|
303
|
+
)
|
|
304
|
+
)
|
|
305
|
+
opts[node_style] = node_style
|
|
306
|
+
|
|
307
|
+
edge_styles = ('edge_line_color', 'edge_line_alpha', 'edge_alpha', 'edge_line_width')
|
|
308
|
+
for edge_style in edge_styles:
|
|
309
|
+
if isinstance(opts.get(edge_style), (np.ndarray, list, range)):
|
|
310
|
+
g = g.add_dimension(edge_style, len(g.vdims), opts[edge_style], True)
|
|
311
|
+
opts[edge_style] = edge_style
|
|
312
|
+
|
|
313
|
+
if opts.get('node_fill_color') in g.nodes.dimensions():
|
|
314
|
+
lims = (kwargs.get('vmin', None), kwargs.get('vmax', None))
|
|
315
|
+
if lims != (None, None):
|
|
316
|
+
dimension = g.nodes.get_dimension(opts.get('node_fill_color'))
|
|
317
|
+
dimension.range = lims
|
|
318
|
+
|
|
319
|
+
if opts.get('edge_line_color') in g.dimensions():
|
|
320
|
+
lims = (kwargs.get('edge_vmin', None), kwargs.get('edge_vmax', None))
|
|
321
|
+
if lims != (None, None):
|
|
322
|
+
dimension = g.get_dimension(opts.get('edge_line_color'))
|
|
323
|
+
dimension.range = lims
|
|
324
|
+
|
|
325
|
+
if inspection_policy == 'nodes':
|
|
326
|
+
tooltip_dims = [
|
|
327
|
+
(d.label, 'index_hover' if d in g.nodes.kdims else d.name)
|
|
328
|
+
for d in g.nodes.kdims[2:] + g.nodes.vdims
|
|
329
|
+
]
|
|
330
|
+
else:
|
|
331
|
+
tooltip_dims = [
|
|
332
|
+
(d.label, d.name + '_values' if d in g.kdims else d.name) for d in g.kdims + g.vdims
|
|
333
|
+
]
|
|
334
|
+
tooltips = [
|
|
335
|
+
(label, '@{%s}' % dimension_sanitizer(name))
|
|
336
|
+
for label, name in tooltip_dims
|
|
337
|
+
if name not in node_styles + edge_styles
|
|
338
|
+
]
|
|
339
|
+
opts['tools'] = [HoverTool(tooltips=tooltips), 'tap']
|
|
340
|
+
|
|
341
|
+
g.opts(**opts, backend='bokeh')
|
|
342
|
+
|
|
343
|
+
# Construct Labels
|
|
344
|
+
if kwargs.get('with_labels', kwargs.get('labels', False)):
|
|
345
|
+
label_opts = {k: kwargs.pop(k) for k in list(kwargs) if k in LabelsPlot.style_opts}
|
|
346
|
+
if 'xoffset' in kwargs:
|
|
347
|
+
label_opts['xoffset'] = kwargs.pop('xoffset')
|
|
348
|
+
if 'yoffset' in kwargs:
|
|
349
|
+
label_opts['yoffset'] = kwargs.pop('yoffset')
|
|
350
|
+
if 'font_size' in kwargs:
|
|
351
|
+
label_opts['text_font_size'] = kwargs.pop('font_size')
|
|
352
|
+
if 'font_color' in kwargs:
|
|
353
|
+
label_opts['text_color'] = kwargs.pop('font_color')
|
|
354
|
+
if 'font_family' in kwargs:
|
|
355
|
+
label_opts['text_font'] = kwargs.pop('font_family')
|
|
356
|
+
labels = kwargs.get('labels', g.nodes.kdims[2])
|
|
357
|
+
if isinstance(labels, dict):
|
|
358
|
+
values = g.nodes.array(g.nodes.kdims)
|
|
359
|
+
data = [(x, y, labels[i]) for (x, y, i) in values if i in labels]
|
|
360
|
+
labels = label_element(data, g.nodes.kdims[:2], 'text', **label_params)
|
|
361
|
+
else:
|
|
362
|
+
labels = label_element(g.nodes, g.nodes.kdims[:2], labels, **label_params)
|
|
363
|
+
g = g * labels.opts(**label_opts, backend='bokeh')
|
|
364
|
+
|
|
365
|
+
# Apply label
|
|
366
|
+
if 'label' in kwargs:
|
|
367
|
+
g = g.relabel(kwargs.pop('label'))
|
|
368
|
+
|
|
369
|
+
# Process options
|
|
370
|
+
g = _transfer_opts_cur_backend(g)
|
|
371
|
+
|
|
372
|
+
return g
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def draw_networkx(G, pos=None, **kwargs):
|
|
376
|
+
"""Draw a networkx graph.
|
|
377
|
+
|
|
378
|
+
Draw the graph with hvPlot with options for node positions,
|
|
379
|
+
labeling, titles, and many other drawing features. See draw() for
|
|
380
|
+
simple drawing without labels or axes.
|
|
381
|
+
|
|
382
|
+
Parameters
|
|
383
|
+
----------
|
|
384
|
+
G : graph
|
|
385
|
+
A networkx graph
|
|
386
|
+
pos : dictionary, optional
|
|
387
|
+
A dictionary with nodes as keys and positions as values or a
|
|
388
|
+
layout `networkx.drawing.layout` function. If not specified a
|
|
389
|
+
spring layout positioning will be computed. See
|
|
390
|
+
:py:mod:`networkx.drawing.layout` for functions that compute
|
|
391
|
+
node positions.
|
|
392
|
+
kwargs : optional keywords
|
|
393
|
+
See hvplot.networkx.draw() for a description of optional
|
|
394
|
+
keywords, with the exception of the pos parameter which is not
|
|
395
|
+
used by this function.
|
|
396
|
+
|
|
397
|
+
Returns
|
|
398
|
+
-------
|
|
399
|
+
graph : holoviews.Graph or holoviews.Overlay
|
|
400
|
+
Graph element
|
|
401
|
+
"""
|
|
402
|
+
kwargs['_axis_defaults'] = False
|
|
403
|
+
return draw(G, pos, **kwargs)
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
def draw_networkx_nodes(G, pos, **kwargs):
|
|
407
|
+
"""Draw networkx graph nodes.
|
|
408
|
+
|
|
409
|
+
Parameters
|
|
410
|
+
----------
|
|
411
|
+
G : graph
|
|
412
|
+
A networkx graph
|
|
413
|
+
kwargs : optional keywords
|
|
414
|
+
See hvplot.networkx.draw() for a description of optional
|
|
415
|
+
keywords, with the exception of the pos parameter which is not
|
|
416
|
+
used by this function.
|
|
417
|
+
|
|
418
|
+
Returns
|
|
419
|
+
-------
|
|
420
|
+
graph: holoviews.Graph or holoviews.Overlay
|
|
421
|
+
Graph element
|
|
422
|
+
"""
|
|
423
|
+
if 'alpha' in kwargs:
|
|
424
|
+
kwargs['node_alpha'] = kwargs.pop('alpha')
|
|
425
|
+
kwargs.pop('edgelist', None)
|
|
426
|
+
kwargs['_axis_defaults'] = False
|
|
427
|
+
kwargs['edge_alpha'] = 0
|
|
428
|
+
kwargs['edge_hover_alpha'] = 0
|
|
429
|
+
kwargs['edge_nonselection_alpha'] = 0
|
|
430
|
+
return draw(G, pos, **kwargs)
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
def draw_networkx_edges(G, pos, **kwargs):
|
|
434
|
+
"""Draw networkx graph edges.
|
|
435
|
+
|
|
436
|
+
Parameters
|
|
437
|
+
----------
|
|
438
|
+
G : graph
|
|
439
|
+
A networkx graph
|
|
440
|
+
kwargs : optional keywords
|
|
441
|
+
See hvplot.networkx.draw() for a description of optional
|
|
442
|
+
keywords, with the exception of the pos parameter which is not
|
|
443
|
+
used by this function.
|
|
444
|
+
|
|
445
|
+
Returns
|
|
446
|
+
-------
|
|
447
|
+
graph : holoviews.Graph or (holoviews.Graph * holoviews.Labels)
|
|
448
|
+
Graph element
|
|
449
|
+
"""
|
|
450
|
+
if 'alpha' in kwargs:
|
|
451
|
+
kwargs['edge_alpha'] = kwargs.pop('alpha')
|
|
452
|
+
kwargs.pop('nodelist', None)
|
|
453
|
+
kwargs['node_alpha'] = 0
|
|
454
|
+
kwargs['node_hover_alpha'] = 0
|
|
455
|
+
kwargs['node_nonselection_alpha'] = 0
|
|
456
|
+
kwargs['_axis_defaults'] = False
|
|
457
|
+
if kwargs.get('selection_policy') is not None:
|
|
458
|
+
kwargs['selection_policy'] = 'edges'
|
|
459
|
+
if kwargs.get('inspection_policy') is not None:
|
|
460
|
+
kwargs['inspection_policy'] = 'edges'
|
|
461
|
+
return draw(G, pos, **kwargs)
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def draw_networkx_labels(G, pos, **kwargs):
|
|
465
|
+
"""Draw networkx graph node labels.
|
|
466
|
+
|
|
467
|
+
Parameters
|
|
468
|
+
----------
|
|
469
|
+
G : graph
|
|
470
|
+
A networkx graph
|
|
471
|
+
kwargs : optional keywords
|
|
472
|
+
See hvplot.networkx.draw() for a description of optional
|
|
473
|
+
keywords, with the exception of the pos parameter which is not
|
|
474
|
+
used by this function.
|
|
475
|
+
|
|
476
|
+
Returns
|
|
477
|
+
-------
|
|
478
|
+
graph : Labels element
|
|
479
|
+
Labels element
|
|
480
|
+
"""
|
|
481
|
+
g = draw(G, pos, **kwargs)
|
|
482
|
+
return Labels(g.nodes, g.nodes.kdims[:2], g.nodes.kdims[2])
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
def draw_circular(G, **kwargs):
|
|
486
|
+
"""Draw networkx graph with circular layout.
|
|
487
|
+
|
|
488
|
+
Parameters
|
|
489
|
+
----------
|
|
490
|
+
G : graph
|
|
491
|
+
A networkx graph
|
|
492
|
+
kwargs : optional keywords
|
|
493
|
+
See hvplot.networkx.draw() for a description of optional
|
|
494
|
+
keywords, with the exception of the pos parameter which is not
|
|
495
|
+
used by this function.
|
|
496
|
+
|
|
497
|
+
Returns
|
|
498
|
+
-------
|
|
499
|
+
graph : holoviews.Graph or holoviews.Overlay
|
|
500
|
+
Graph element or Graph and Labels
|
|
501
|
+
"""
|
|
502
|
+
return draw(G, pos=nx.circular_layout, **kwargs)
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
def draw_kamada_kawai(G, **kwargs):
|
|
506
|
+
"""Draw networkx graph with circular layout.
|
|
507
|
+
|
|
508
|
+
Parameters
|
|
509
|
+
----------
|
|
510
|
+
G : graph
|
|
511
|
+
A networkx graph
|
|
512
|
+
kwargs : optional keywords
|
|
513
|
+
See hvplot.networkx.draw() for a description of optional
|
|
514
|
+
keywords, with the exception of the pos parameter which is not
|
|
515
|
+
used by this function.
|
|
516
|
+
|
|
517
|
+
Returns
|
|
518
|
+
-------
|
|
519
|
+
graph : holoviews.Graph or holoviews.Overlay
|
|
520
|
+
Graph element or Graph and Labels
|
|
521
|
+
"""
|
|
522
|
+
return draw(G, pos=nx.kamada_kawai_layout, **kwargs)
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
def draw_random(G, **kwargs):
|
|
526
|
+
"""Draw networkx graph with random layout.
|
|
527
|
+
|
|
528
|
+
Parameters
|
|
529
|
+
----------
|
|
530
|
+
G : graph
|
|
531
|
+
A networkx graph
|
|
532
|
+
kwargs : optional keywords
|
|
533
|
+
See hvplot.networkx.draw() for a description of optional
|
|
534
|
+
keywords, with the exception of the pos parameter which is not
|
|
535
|
+
used by this function.
|
|
536
|
+
|
|
537
|
+
Returns
|
|
538
|
+
-------
|
|
539
|
+
graph : holoviews.Graph or holoviews.Overlay
|
|
540
|
+
Graph element
|
|
541
|
+
"""
|
|
542
|
+
return draw(G, nx.random_layout, **kwargs)
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
def draw_shell(G, **kwargs):
|
|
546
|
+
"""Draw networkx graph with shell layout.
|
|
547
|
+
|
|
548
|
+
Parameters
|
|
549
|
+
----------
|
|
550
|
+
G : graph
|
|
551
|
+
A networkx graph
|
|
552
|
+
kwargs : optional keywords
|
|
553
|
+
See hvplot.networkx.draw() for a description of optional
|
|
554
|
+
keywords, with the exception of the pos parameter which is not
|
|
555
|
+
used by this function.
|
|
556
|
+
|
|
557
|
+
Returns
|
|
558
|
+
-------
|
|
559
|
+
graph : holoviews.Graph or holoviews.Overlay
|
|
560
|
+
Graph element or Graph and Labels
|
|
561
|
+
"""
|
|
562
|
+
nlist = kwargs.pop('nlist', None)
|
|
563
|
+
if nlist is not None:
|
|
564
|
+
kwargs['layout_kwargs'] = {'nlist': nlist}
|
|
565
|
+
return draw(G, nx.shell_layout, **kwargs)
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
def draw_spectral(G, **kwargs):
|
|
569
|
+
"""Draw networkx graph with spectral layout.
|
|
570
|
+
|
|
571
|
+
Parameters
|
|
572
|
+
----------
|
|
573
|
+
G : graph
|
|
574
|
+
A networkx graph
|
|
575
|
+
kwargs : optional keywords
|
|
576
|
+
See hvplot.networkx.draw() for a description of optional
|
|
577
|
+
keywords, with the exception of the pos parameter which is not
|
|
578
|
+
used by this function.
|
|
579
|
+
|
|
580
|
+
Returns
|
|
581
|
+
-------
|
|
582
|
+
graph : holoviews.Graph or holoviews.Overlay
|
|
583
|
+
Graph element or Graph and Labels
|
|
584
|
+
"""
|
|
585
|
+
return draw(G, nx.spectral_layout, **kwargs)
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
def draw_spring(G, **kwargs):
|
|
589
|
+
"""Draw networkx graph with spring layout.
|
|
590
|
+
|
|
591
|
+
Parameters
|
|
592
|
+
----------
|
|
593
|
+
G : graph
|
|
594
|
+
A networkx graph
|
|
595
|
+
kwargs : optional keywords
|
|
596
|
+
See hvplot.networkx.draw() for a description of optional
|
|
597
|
+
keywords, with the exception of the pos parameter which is not
|
|
598
|
+
used by this function.
|
|
599
|
+
|
|
600
|
+
Returns
|
|
601
|
+
-------
|
|
602
|
+
graph : holoviews.Graph or holoviews.Overlay
|
|
603
|
+
Graph element or Graph and Labels
|
|
604
|
+
"""
|
|
605
|
+
return draw(G, nx.spring_layout, **kwargs)
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
def draw_planar(G, **kwargs):
|
|
609
|
+
"""Draw networkx graph with planar layout.
|
|
610
|
+
|
|
611
|
+
Parameters
|
|
612
|
+
----------
|
|
613
|
+
G : graph
|
|
614
|
+
A networkx graph
|
|
615
|
+
kwargs : optional keywords
|
|
616
|
+
See hvplot.networkx.draw() for a description of optional
|
|
617
|
+
keywords, with the exception of the pos parameter which is not
|
|
618
|
+
used by this function.
|
|
619
|
+
|
|
620
|
+
Returns
|
|
621
|
+
-------
|
|
622
|
+
graph : holoviews.Graph or holoviews.Overlay
|
|
623
|
+
Graph element or Graph and Labels
|
|
624
|
+
"""
|
|
625
|
+
return draw(G, nx.planar_layout, **kwargs)
|
hvplot/pandas.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Adds the `.hvplot` method to pd.DataFrame and pd.Series"""
|
|
2
|
+
|
|
3
|
+
from .interactive import Interactive
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def patch(name='hvplot', interactive='interactive', extension='bokeh', logo=False):
|
|
7
|
+
from . import hvPlotTabular, post_patch
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
import pandas as pd
|
|
11
|
+
except ImportError:
|
|
12
|
+
raise ImportError(
|
|
13
|
+
'Could not patch plotting API onto pandas. Pandas could not be imported.'
|
|
14
|
+
)
|
|
15
|
+
_patch_plot = lambda self: hvPlotTabular(self) # noqa: E731
|
|
16
|
+
_patch_plot.__doc__ = hvPlotTabular.__call__.__doc__
|
|
17
|
+
plot_prop = property(_patch_plot)
|
|
18
|
+
setattr(pd.DataFrame, name, plot_prop)
|
|
19
|
+
setattr(pd.Series, name, plot_prop)
|
|
20
|
+
|
|
21
|
+
_patch_interactive = lambda self: Interactive(self) # noqa: E731
|
|
22
|
+
_patch_interactive.__doc__ = Interactive.__call__.__doc__
|
|
23
|
+
interactive_prop = property(_patch_interactive)
|
|
24
|
+
setattr(pd.DataFrame, interactive, interactive_prop)
|
|
25
|
+
setattr(pd.Series, interactive, interactive_prop)
|
|
26
|
+
|
|
27
|
+
post_patch(extension, logo)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
patch()
|