pyvis
pyvis copied to clipboard
How does one use str ids when calling add_nodes()?
I'm brand new to this library, so apologies if this is something silly I'm missing.
The docs suggest that nodes can have int or str ids:
n_id (str or int) – The id of the node. The id is mandatory for nodes and they have to be unique. This should obviously be set per node, not globally.
The documentation for add_nodes() doesn't say this explicitly, but my assumption was that globally one could use int or str for node ids. I get different behavior between the two functions:
from pyvis.network import Network
net1 = Network(notebook=True)
net2 = Network(notebook=True)
nodes = ['01', '02']
for n in nodes:
net1.add_node(n, label=n)
print(net1.nodes)
net2.add_nodes(nodes, label=nodes)
print(net2.nodes)
Result (note discrepancy between id values):
[{'color': '#97c2fc', 'id': '01', 'label': '01', 'shape': 'dot'}, {'color': '#97c2fc', 'id': '02', 'label': '02', 'shape': 'dot'}]
[{'color': '#97c2fc', 'id': 1, 'label': 1, 'shape': 'dot'}, {'color': '#97c2fc', 'id': 2, 'label': 2, 'shape': 'dot'}]
Maybe add_nodes() doesn't say in the docs, but was designed only to take int ids. But this becomes a problem with add_edges(), as it is preserving str ids.
net2.add_edges([('01', '02')])
AssertionError Traceback (most recent call last)
Cell In[167], line 1
----> 1 net2.add_edges([('01', '02')])
[...]
AssertionError: non existent node '01'
Could someone let me know if I'm misunderstanding the usage, or could this be a bug where the single and bulk calls need to be aligned in behavior?
Took a look and found what I think this issue is here.
for node in nodes:
# check if node is `number-like`
try:
node = int(node)
self.add_node(node, **nd[node])
except:
# or node could be string
assert isinstance(node, str)
self.add_node(node, **nd[node])
So if one has str ids that could be int convertible (as my test case / real world example can), it's not possible to preserve the str type when calling bulk add.
add_edges doesn't do this, directly (and blindly) passing the args to add_edge.
for edge in edges:
# if incoming tuple contains a weight
if len(edge) == 3:
self.add_edge(edge[0], edge[1], width=edge[2])
else:
self.add_edge(edge[0], edge[1])
In my view, have add_nodes just check for a valid type, but do not alter it. So something like:
for node in nodes:
if isinstance(node, int) or isinstance(node, str):
self.add_node(node, **nd[node])
else:
# error handling for improper id type
Also, I like how the args are parsed for nodes; it appears one can't pass keywords to add_edges() and thus add_edge() is far more flexible... thoughts on allowing add_edges() to take any of the args add_edge() will accpet?