NetworkX has no functions to merge nodes in the graph so it should be implemented manually. Here is the example without attributes merging (it can has its own logic):
def merge(G, n1, n2):
# Get all predecessors and successors of two nodes
pre = set(G.predecessors(n1)) | set(G.predecessors(n2))
suc = set(G.successors(n1)) | set(G.successors(n2))
# Create the new node with combined name
name = str(n1) + '/' + str(n2)
# Add predecessors and successors edges
# We have DiGraph so there should be one edge per nodes pair
G.add_edges_from([(p, name) for p in pre])
G.add_edges_from([(name, s) for s in suc])
# Remove old nodes
G.remove_nodes_from([n1, n2])
Here is how it works:
import networkx as nx
G = nx.DiGraph()
G.add_edges_from([
('0','20'),
('10','20'),
('10','30'),
('20','40'),
('30','50'),
])
nx.draw(
G,
pos=nx.nx_agraph.graphviz_layout(G, prog='dot'),
node_color='#FF0000',
with_labels=True
)

merge(G, '20', '30')
nx.draw(
G,
pos=nx.nx_agraph.graphviz_layout(G, prog='dot'),
node_color='#FF0000',
with_labels=True
)
