class_docstr: Graph is high-level Element representing both nodes and edges.
  A Graph may be defined in an abstract form representing just
  the abstract edges between nodes and optionally may be made
  concrete by supplying a Nodes Element defining the concrete
  positions of each node. If the node positions are supplied
  the EdgePaths (defining the concrete edges) can be inferred
  automatically or supplied explicitly.
  
  The constructor accepts regular columnar data defining the edges
  or a tuple of the abstract edges and nodes, or a tuple of the
  abstract edges, nodes, and edgepaths.
class_docstr_tok: ["Graph","is","high-level","Element","representing","both","nodes","and","edges",".","A","Graph","may","be","defined","in","an","abstract","form","representing","just","the","abstract","edges","between","nodes","and","optionally","may","be","made","concrete","by","supplying","a","Nodes","Element","defining","the","concrete","positions","of","each","node",".","If","the","node","positions","are","supplied","the","EdgePaths","(","defining","the","concrete","edges",")","can","be","inferred","automatically","or","supplied","explicitly",".","The","constructor","accepts","regular","columnar","data","defining","the","edges","or","a","tuple","of","the","abstract","edges","and","nodes",",","or","a","tuple","of","the","abstract","edges",",","nodes",",","and","edgepaths","."]
docstr: Generate a HoloViews Graph from a networkx.Graph object and
  networkx layout function or dictionary of node positions.
  Any keyword arguments will be passed to the layout
  function. By default it will extract all node and edge
  attributes from the networkx.Graph but explicit node
  information may also be supplied. Any non-scalar attributes,
  such as lists or dictionaries will be ignored.
  
  Args:
      G (networkx.Graph): Graph to convert to Graph element
      positions (dict or callable): Node positions
          Node positions defined as a dictionary mapping from
          node id to (x, y) tuple or networkx layout function
          which computes a positions dictionary
      kwargs (dict): Keyword arguments for layout function
  
  Returns:
      Graph element
docstr_tok: ["Generate","a","HoloViews","Graph","from","a","networkx.Graph","object","and","networkx","layout","function","or","dictionary","of","node","positions",".","Any","keyword","arguments","will","be","passed","to","the","layout","function",".","By","default","it","will","extract","all","node","and","edge","attributes","from","the","networkx.Graph","but","explicit","node","information","may","also","be","supplied",".","Any","non-scalar","attributes",",","such","as","lists","or","dictionaries","will","be","ignored",".","Args",":","G","(","networkx.Graph",")",":","Graph","to","convert","to","Graph","element","positions","(","dict","or","callable",")",":","Node","positions","Node","positions","defined","as","a","dictionary","mapping","from","node","id","to","(","x",",","y",")","tuple","or","networkx","layout","function","which","computes","a","positions","dictionary","kwargs","(","dict",")",":","Keyword","arguments","for","layout","function","Returns",":","Graph","element"]
code: def from_networkx(cls, G, positions, nodes=None, **kwargs):
      """
      Generate a HoloViews Graph from a networkx.Graph object and
      networkx layout function or dictionary of node positions.
      Any keyword arguments will be passed to the layout
      function. By default it will extract all node and edge
      attributes from the networkx.Graph but explicit node
      information may also be supplied. Any non-scalar attributes,
      such as lists or dictionaries will be ignored.
  
      Args:
          G (networkx.Graph): Graph to convert to Graph element
          positions (dict or callable): Node positions
              Node positions defined as a dictionary mapping from
              node id to (x, y) tuple or networkx layout function
              which computes a positions dictionary
          kwargs (dict): Keyword arguments for layout function
  
      Returns:
          Graph element
      """
      if not isinstance(positions, dict):
          positions = positions(G, **kwargs)
  
      # Unpack edges
      edges = defaultdict(list)
      for start, end in G.edges():
          for attr, value in sorted(G.adj[start][end].items()):
              if isinstance(value, (list, dict)):
                  continue  # Cannot handle list or dict attrs
              edges[attr].append(value)
  
          # Handle tuple node indexes (used in 2D grid Graphs)
          if isinstance(start, tuple):
              start = str(start)
          if isinstance(end, tuple):
              end = str(end)
          edges["start"].append(start)
          edges["end"].append(end)
      edge_cols = sorted(
          [
              k
              for k in edges
              if k not in ("start", "end")
              and len(edges[k]) == len(edges["start"])
          ]
      )
      edge_vdims = [
          str(col) if isinstance(col, int) else col for col in edge_cols
      ]
      edge_data = tuple(
          edges[col] for col in ["start", "end"] + edge_cols
      )
  
      # Unpack user node info
      xdim, ydim, idim = cls.node_type.kdims[:3]
      if nodes:
          node_columns = nodes.columns()
          idx_dim = nodes.kdims[0].name
          info_cols, values = zip(
              *((k, v) for k, v in node_columns.items() if k != idx_dim)
          )
          node_info = {
              i: vals
              for i, vals in zip(node_columns[idx_dim], zip(*values))
          }
      else:
          info_cols = []
          node_info = None
      node_columns = defaultdict(list)
  
      # Unpack node positions
      for idx, pos in sorted(positions.items()):
          node = G.nodes.get(idx)
          if node is None:
              continue
          x, y = pos
          node_columns[xdim.name].append(x)
          node_columns[ydim.name].append(y)
          for attr, value in node.items():
              if isinstance(value, (list, dict)):
                  continue
              node_columns[attr].append(value)
          for i, col in enumerate(info_cols):
              node_columns[col].append(node_info[idx][i])
          if isinstance(idx, tuple):
              idx = str(idx)  # Tuple node indexes handled as strings
          node_columns[idim.name].append(idx)
      node_cols = sorted(
          [
              k
              for k in node_columns
              if k not in cls.node_type.kdims
              and len(node_columns[k]) == len(node_columns[xdim.name])
          ]
      )
      columns = (
          [xdim.name, ydim.name, idim.name]
          + node_cols
          + list(info_cols)
      )
      node_data = tuple(node_columns[col] for col in columns)
  
      # Construct nodes
      vdims = []
      for col in node_cols:
          if isinstance(col, int):
              dim = str(col)
          elif nodes is not None and col in nodes.vdims:
              dim = nodes.get_dimension(col)
          else:
              dim = col
          vdims.append(dim)
      nodes = cls.node_type(node_data, vdims=vdims)
  
      # Construct graph
      return cls((edge_data, nodes), vdims=edge_vdims)
  
imports: from collections import defaultdict
  from types import FunctionType
  import numpy
  import pandas
  import param
  from ..core import Dataset, Dimension, Element2D
  from ..core.accessors import Redim
  from ..core.operation import Operation
  from ..core.util import is_dataframe, max_range, search_indices
  from .chart import Points
  from .path import Path
  from .util import circular_layout, connect_edges_pd, connect_tri_edges_pd, quadratic_bezier, split_path
label_desc: Use image node_id 12 for calling the Graph obj's underlying member method code with example usage: obj.from_networkx(cls, G, positions, nodes) and returns: cls