code: def multi_indexing(data, i, indexing=None):
      
      # in case of i being a numpy array
      i = _normalize_numpy_indices(i)
  
      # If we already know how to index, use that knowledge
      if indexing is not None:
          return indexing(data, i)
  
      # If we don't know how to index, find out and apply
      return check_indexing(data)(data, i)
docs: Perform indexing on multiple data structures.
  
      Currently supported data types:
  
      * numpy arrays
      * torch tensors
      * pandas NDFrame
      * a dictionary of the former three
      * a list/tuple of the former three
  
      ``i`` can be an integer or a slice.
  
      Examples
      --------
      >>> multi_indexing(np.asarray([1, 2, 3]), 0)
      1
  
      >>> multi_indexing(np.asarray([1, 2, 3]), np.s_[:2])
      array([1, 2])
  
      >>> multi_indexing(torch.arange(0, 4), np.s_[1:3])
      tensor([ 1.,  2.])
  
      >>> multi_indexing([[1, 2, 3], [4, 5, 6]], np.s_[:2])
      [[1, 2], [4, 5]]
  
      >>> multi_indexing({'a': [1, 2, 3], 'b': [4, 5, 6]}, np.s_[-2:])
      {'a': [2, 3], 'b': [5, 6]}
  
      >>> multi_indexing(pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]}), [1, 2])
         a  b
      1  2  5
      2  3  6
  
      Parameters
      ----------
      data
        Data of a type mentioned above.
  
      i : int or slice
        Slicing index.
  
      indexing : function/callable or None (default=None)
        If not None, use this function for indexing into the data. If
        None, try to automatically determine how to index data.