docs: def change_numbering(self, new_index=None):
          """Change numbering to a new index.
  
          Changes the numbering of index and all dependent numbering
              (bond_with...) to a new_index.
          The user has to make sure that the new_index consists of distinct
              elements.
  
          Args:
              new_index (list): If None the new_index is taken from 1 to the
                  number of atoms.
  
          Returns:
              Zmat: Reindexed version of the zmatrix.
          """
          if (new_index is None):
              new_index = range(len(self))
          elif len(new_index) != len(self):
              raise ValueError('len(new_index) has to be the same as len(self)')
  
          c_table = self.loc[:, ['b', 'a', 'd']]
          # Strange bug in pandas where .replace is transitive for object columns
          # and non-transitive for all other types.
          # (Remember that string columns are just object columns)
          # Example:
          # A = {1: 2, 2: 3}
          # Transtitive [1].replace(A) gives [3]
          # Non-Transtitive [1].replace(A) gives [2]
          # https://github.com/pandas-dev/pandas/issues/5338
          # https://github.com/pandas-dev/pandas/issues/16051
          # https://github.com/pandas-dev/pandas/issues/5541
          # For this reason convert to int and replace then.
  
          c_table = c_table.replace(constants.int_label)
          try:
              c_table = c_table.astype('i8')
          except ValueError:
              raise ValueError('Due to a bug in pandas it is necessary to have '
                               'integer columns')
          c_table = c_table.replace(self.index, new_index)
          c_table = c_table.replace(
              {v: k for k, v in constants.int_label.items()})
  
          out = self.copy()
          out.unsafe_loc[:, ['b', 'a', 'd']] = c_table
          out._frame.index = new_index
          return out