code: def from_networkx(
      G: Any,
      group_node_attrs: Optional[
          Union[List[str], Literal["all"]]
      ] = None,
      group_edge_attrs: Optional[
          Union[List[str], Literal["all"]]
      ] = None,
  ) -> "torch_geometric.data.Data":
      r"""Converts a :obj:`networkx.Graph` or :obj:`networkx.DiGraph` to a
      :class:`torch_geometric.data.Data` instance.
  
      Args:
          G (networkx.Graph or networkx.DiGraph): A networkx graph.
          group_node_attrs (List[str] or "all", optional): The node attributes to
              be concatenated and added to :obj:`data.x`. (default: :obj:`None`)
          group_edge_attrs (List[str] or "all", optional): The edge attributes to
              be concatenated and added to :obj:`data.edge_attr`.
              (default: :obj:`None`)
  
      .. note::
  
          All :attr:`group_node_attrs` and :attr:`group_edge_attrs` values must
          be numeric.
  
      Examples:
          >>> edge_index = torch.tensor([
          ...     [0, 1, 1, 2, 2, 3],
          ...     [1, 0, 2, 1, 3, 2],
          ... ])
          >>> data = Data(edge_index=edge_index, num_nodes=4)
          >>> g = to_networkx(data)
          >>> # A `Data` object is returned
          >>> from_networkx(g)
          Data(edge_index=[2, 6], num_nodes=4)
      """
      import networkx as nx
  
      from torch_geometric.data import Data
  
      G = G.to_directed() if not nx.is_directed(G) else G
  
      mapping = dict(zip(G.nodes(), range(G.number_of_nodes())))
      edge_index = torch.empty(
          (2, G.number_of_edges()), dtype=torch.long
      )
      for i, (src, dst) in enumerate(G.edges()):
          edge_index[0, i] = mapping[src]
          edge_index[1, i] = mapping[dst]
  
      data_dict: Dict[str, Any] = defaultdict(list)
      data_dict["edge_index"] = edge_index
  
      node_attrs: List[str] = []
      if G.number_of_nodes() > 0:
          node_attrs = list(next(iter(G.nodes(data=True)))[-1].keys())
  
      edge_attrs: List[str] = []
      if G.number_of_edges() > 0:
          edge_attrs = list(next(iter(G.edges(data=True)))[-1].keys())
  
      if group_node_attrs is not None and not isinstance(
          group_node_attrs, list
      ):
          group_node_attrs = node_attrs
  
      if group_edge_attrs is not None and not isinstance(
          group_edge_attrs, list
      ):
          group_edge_attrs = edge_attrs
  
      for i, (_, feat_dict) in enumerate(G.nodes(data=True)):
          if set(feat_dict.keys()) != set(node_attrs):
              raise ValueError(
                  "Not all nodes contain the same attributes"
              )
          for key, value in feat_dict.items():
              data_dict[str(key)].append(value)
  
      for i, (_, _, feat_dict) in enumerate(G.edges(data=True)):
          if set(feat_dict.keys()) != set(edge_attrs):
              raise ValueError(
                  "Not all edges contain the same attributes"
              )
          for key, value in feat_dict.items():
              key = f"edge_{key}" if key in node_attrs else key
              data_dict[str(key)].append(value)
  
      for key, value in G.graph.items():
          if key == "node_default" or key == "edge_default":
              continue  # Do not load default attributes.
          key = f"graph_{key}" if key in node_attrs else key
          data_dict[str(key)] = value
  
      for key, value in data_dict.items():
          if isinstance(value, (tuple, list)) and isinstance(
              value[0], Tensor
          ):
              data_dict[key] = torch.stack(value, dim=0)
          else:
              try:
                  data_dict[key] = torch.as_tensor(value)
              except Exception:
                  pass
  
      data = Data.from_dict(data_dict)
  
      if group_node_attrs is not None:
          xs = []
          for key in group_node_attrs:
              x = data[key]
              x = x.view(-1, 1) if x.dim() <= 1 else x
              xs.append(x)
              del data[key]
          data.x = torch.cat(xs, dim=-1)
  
      if group_edge_attrs is not None:
          xs = []
          for key in group_edge_attrs:
              key = f"edge_{key}" if key in node_attrs else key
              x = data[key]
              x = x.view(-1, 1) if x.dim() <= 1 else x
              xs.append(x)
              del data[key]
          data.edge_attr = torch.cat(xs, dim=-1)
  
      if data.x is None and data.pos is None:
          data.num_nodes = G.number_of_nodes()
  
      return data
  
file_path: pytorch_geometric/torch_geometric/utils/convert.py
imports: from collections import defaultdict
  from typing import Any, Dict, Iterable, List, Literal, Optional, Tuple, Union
  import scipy.sparse
  import torch
  from torch import Tensor
  from torch.utils.dlpack import from_dlpack, to_dlpack
  import torch_geometric
  from torch_geometric.utils.num_nodes import maybe_num_nodes
label_desc: Use image node_id 4 for calling a global function with example usage: from_networkx(G, group_node_attrs, group_edge_attrs) and returns: data