class_docstr: A plain python object modeling a heterogeneous graph with various
  attributes (Node types in :class:`HeteroGraph` require string type).
  
  Args:
      G (:class:`networkx.classes.graph`): A NetworkX graph object which
          contains features and labels for each node type and edge type.
      **kwargs: Keyworded argument list with keys such
          as :obj:`"node_feature"`, :obj:`"node_label"` and
          corresponding attributes.
class_docstr_tok: ["A","plain","python","object","modeling","a","heterogeneous","graph","with","various","attributes","(","Node","types","in",":","class",":","`","HeteroGraph","`","require","string","type",")",".","Args",":","G","(",":","class",":","`","networkx.classes.graph","`",")",":","A","NetworkX","graph","object","which","contains","features","and","labels","for","each","node","type","and","edge","type",".","*","*","kwargs",":","Keyworded","argument","list","with","keys","such","as",":","obj",":","`","``","node_feature","''","`",",",":","obj",":","`","``","node_label","''","`","and","corresponding","attributes","."]
docstr: Split the graph into len(split_ratio) graphs for node prediction.
  Internally this splits node indices, and the model will only compute
  loss for the embedding of
  nodes in each split graph.
  In node classification, the whole graph is observed in train/val/test
  Only split over node_label_index
docstr_tok: ["Split","the","graph","into","len","(","split_ratio",")","graphs","for","node","prediction",".","Internally","this","splits","node","indices",",","and","the","model","will","only","compute","loss","for","the","embedding","of","nodes","in","each","split","graph",".","In","node","classification",",","the","whole","graph","is","observed","in","train\/val\/test","Only","split","over","node_label_index"]
code: def _split_node(
      self,
      split_types: List[str],
      split_ratio: float,
      shuffle: bool = True,
  ):
      r"""
      Split the graph into len(split_ratio) graphs for node prediction.
      Internally this splits node indices, and the model will only compute
      loss for the embedding of
      nodes in each split graph.
      In node classification, the whole graph is observed in train/val/test
      Only split over node_label_index
      """
      if isinstance(split_types, list):
          for split_type in split_types:
              if split_type not in self.node_types:
                  raise TypeError(
                      "all split_type in split_types need to be in "
                      f"{self.node_types}, however split type: "
                      "{split_type} is in split_types."
                  )
      elif split_types is None:
          split_types = self.node_types
      else:
          if split_types not in self.node_types:
              raise TypeError(
                  f"split_types need to be in {self.node_types}, "
                  f"however split_types is: {split_types}."
              )
          else:
              split_types = [split_types]
  
      for split_type, num_node_type in self.num_nodes(
          split_types
      ).items():
          if num_node_type < len(split_ratio):
              raise ValueError(
                  f"In _split_node num of nodes of node_type: {split_type} "
                  "are smaller than number of splitted parts."
              )
      split_graphs = []
      for _ in range(len(split_ratio)):
          graph_new = copy.copy(self)
          graph_new.node_label_index = {}
          graph_new.node_label = {}
          split_graphs.append(graph_new)
  
      for split_type in self.node_types:
          if split_type in split_types:
              split_type_nodes_length = self.num_nodes(split_type)
              if shuffle:
                  split_type_node = self.node_label_index[split_type][
                      torch.randperm(split_type_nodes_length)
                  ]
              else:
                  split_type_node = self.node_label_index[split_type]
  
              # used to indicate whether default splitting results in
              # empty splitted graphs
              split_empty_flag = False
              nodes_split_list = []
  
              # perform `default split`
              split_offset = 0
              for i, split_ratio_i in enumerate(split_ratio):
                  if i != len(split_ratio) - 1:
                      num_split_i = int(
                          split_ratio_i * split_type_nodes_length
                      )
                      nodes_split_i = split_type_node[
                          split_offset : split_offset + num_split_i
                      ]
                      split_offset += num_split_i
                  else:
                      nodes_split_i = split_type_node[split_offset:]
                  if nodes_split_i.numel() == 0:
                      split_empty_flag = True
                      split_offset = 0
                      nodes_split_list = []
                      break
                  nodes_split_list.append(nodes_split_i)
  
              if split_empty_flag:
                  for i, split_ratio_i in enumerate(split_ratio):
                      # perform `secure split` s.t. guarantees all
                      # splitted subgraph of a split type contains at
                      # least one node.
                      if i != len(split_ratio) - 1:
                          num_split_i = 1 + int(
                              split_ratio_i
                              * (
                                  split_type_nodes_length
                                  - len(split_ratio)
                              )
                          )
                          nodes_split_i = split_type_node[
                              split_offset : split_offset + num_split_i
                          ]
                          split_offset += num_split_i
                      else:
                          nodes_split_i = split_type_node[split_offset:]
                      nodes_split_list.append(nodes_split_i)
  
              for idx, nodes_split_i in enumerate(nodes_split_list):
                  split_graphs[idx].node_label_index[
                      split_type
                  ] = nodes_split_i
                  split_graphs[idx].node_label[
                      split_type
                  ] = self.node_label[split_type][nodes_split_i]
          else:
              for idx, graph in enumerate(split_graphs):
                  graph.node_label_index[
                      split_type
                  ] = self.node_label_index[split_type]
                  graph.node_label[split_type] = self.node_label[
                      split_type
                  ]
                  split_graphs[idx] = graph
  
      return split_graphs
  
imports: import math
  import copy
  import random
  import torch
  import networkx
  import numpy
  from deepsnap.graph import Graph
  from typing import Dict, List, Union
  import warnings
label_desc: Use image node_id 29 for calling the HeteroGraph obj's underlying member method code with example usage: obj._split_node(split_types, split_ratio, shuffle) and returns: split_graphs