Guiding Layout with Edge Weights#
We can use edge attributes to guide the layout by having how much the nodes of an edge get attracted to one another be influenced by that attribute. This is useful in several scenarios: * An edge has a natural property, such as affinity
* An edge represents multiple edges and thus represents a non-uniform weight such as count
* Algorithms provide edge properties, such as relevance
By binding such an edge column to edge_weight and optionally tuning how much to factor in that column with the edgeInfluence control, we can guide the clustering to factor in the edge weight.
By default, every edge contributes a weight of
1
on how much to pull its nodes together.
Multiple edges between the same 2 nodes will thus cause those nodes to be closer together
Activate edge weights in
api=3
(2.0): Edges with high edge weights bring their nodes closer together; edges with low weight allow their nodes to move further appart
Set via binding
edge_weight
(.bind(edge_weight='my_col')
)Edge weight values automatically normalize between 0 and 1 starting with v2.30.25
The edge influence control guides whether to ignore edge weight (
0
) and use it primarily (7+
)
Set via the UI (
Layout Controls
->Edge Influence
) or via url parameteredgeInfluence
(.settings(url_params={'edgeInfluence': 2})
)
[ ]:
import pandas as pd, graphistry
[ ]:
# To specify Graphistry account & server, use:
# graphistry.register(api=3, username='...', password='...', protocol='https', server='hub.graphistry.com')
# For more options, see https://github.com/graphistry/pygraphistry#configure
Demo: Strongly connected graph of 20 nodes#
No edge weight: Appears as a regular mesh
Same edge weights: Appears as a regular mesh
Edge weight
1
for edges (i
,i+1
), defining a chain, and the other edges set to weight0
:'edgeInfluence': 0
: Appears as a regular mesh'edgeInfluence': 1
: Still a mesh, but start to see a chain interleaved'edgeInfluence': 2
: The chain starts to form a circle around the mesh'edgeInfluence': 7
: The chain starts to become a straight line; the other edges have little relative impact (no more mesh)
Edge weight
100
instead of1
for the chain: same as edge weight1
due to normalizationEdge weight
1
for the chain’s edges and-1
for the rest: Same due to normalization
[ ]:
edges = []
n = 20
k = 2
edges = pd.DataFrame({
's': [i for i in range(0,n) for j in range(0,n) if i != j],
'd': [j for i in range(0,n) for j in range(0,n) if i != j]
})
edges['1_if_neighbor'] = edges.apply(
lambda r: \
1 \
if (r['s'] == r['d'] - 1) \
or (r['s'] == r['d'] + 1) \
else 0,
axis=1).astype('float32')
edges['100_if_neighbor'] = (edges['1_if_neighbor'] * 100).astype('int64')
edges['ec'] = edges['1_if_neighbor'].apply(lambda v: round(v) * 0xFF000000)
edges.head(20)
[ ]:
URL_PARAMS = {'play': 5000, 'edgeCurvature': 0.1, 'precisionVsSpeed': -3}
g = graphistry.edges(edges).bind(source='s', destination='d', edge_color='ec').settings(url_params=URL_PARAMS)
Edge Influence 0: No weights – a mesh#
[ ]:
g.bind(edge_weight='1_if_neighbor').settings(url_params={**URL_PARAMS, 'edgeInfluence': 0}).plot(render=True)
Edge influence 1: Some weight – chain interleaved into the mesh#
[ ]:
g.bind(edge_weight='1_if_neighbor').settings(url_params={**URL_PARAMS, 'edgeInfluence': 1}).plot(render=True)
Edge influence 2: Strong weight – chain becomes circumference of mesh#
[ ]:
g.bind(edge_weight='1_if_neighbor').settings(url_params={**URL_PARAMS, 'edgeInfluence': 2}).plot(render=True)
Edge influence 7: Non-chain edges lose relative influence – chain becomes a straight line (no more mesh)#
[ ]:
g.bind(edge_weight='1_if_neighbor').settings(url_params={**URL_PARAMS, 'edgeInfluence': 7}).plot(render=True)
Edge weights -1 to 1, and 0 to 100: Same as if edge weights were between 0 and 1#
Graphistry automatically normalizes edge weights in version 2.30.25+
[ ]:
g.edges(g._edges.assign(with_negative=\
g._edges['1_if_neighbor'].apply(lambda v: \
-1 if v == 0 else 1 )))\
.bind(edge_weight='1_if_neighbor').settings(url_params={**URL_PARAMS, 'edgeInfluence': 1}).plot(render=True)
[ ]:
g.bind(edge_weight='100_if_neighbor').settings(url_params={**URL_PARAMS, 'edgeInfluence': 2}).plot(render=True)
[ ]: