class_docstr: Balance binary or multiclass datasets by duplicating rarer class samples.
  
  This class balances a dataset by duplicating samples of the rarer class so
  that the sum of all example weights from all classes is the same. (Up to
  integer rounding of course). This can be useful when you're working on an
  imabalanced dataset where there are far fewer examples of some classes than
  others.
  
  This class differs from `BalancingTransformer` in that it actually
  duplicates rarer class samples rather than just increasing their sample
  weights. This may be more friendly for models that are numerically fragile
  and can't handle imbalanced example weights.
  
  Examples
  --------
  Here's an example for a binary dataset.
  
  >>> n_samples = 10
  >>> n_features = 3
  >>> n_tasks = 1
  >>> n_classes = 2
  >>> import deepchem as dc
  >>> import numpy as np
  >>> ids = np.arange(n_samples)
  >>> X = np.random.rand(n_samples, n_features)
  >>> y = np.random.randint(n_classes, size=(n_samples, n_tasks))
  >>> w = np.ones((n_samples, n_tasks))
  >>> dataset = dc.data.NumpyDataset(X, y, w, ids)
  >>> transformer = dc.trans.DuplicateBalancingTransformer(dataset=dataset)
  >>> dataset = transformer.transform(dataset)
  
  And here's a multiclass dataset example.
  
  >>> n_samples = 50
  >>> n_features = 3
  >>> n_tasks = 1
  >>> n_classes = 5
  >>> ids = np.arange(n_samples)
  >>> X = np.random.rand(n_samples, n_features)
  >>> y = np.random.randint(n_classes, size=(n_samples, n_tasks))
  >>> w = np.ones((n_samples, n_tasks))
  >>> dataset = dc.data.NumpyDataset(X, y, w, ids)
  >>> transformer = dc.trans.DuplicateBalancingTransformer(dataset=dataset)
  >>> dataset = transformer.transform(dataset)
  
  See Also
  --------
  deepchem.trans.BalancingTransformer: Balance by changing sample weights.
  
  Note
  ----
  This transformer is only well-defined for singletask datasets. (Since
  examples are actually duplicated, there's no meaningful way to duplicate
  across multiple tasks in a way that preserves the balance.)
  
  This transformer is only meaningful for classification datasets where `y`
  takes on a limited set of values. This class transforms all of `X`, `y`,
  `w`, `ids`.
  
  Raises
  ------
  `ValueError` if the provided dataset is multitask.
docstr: Transform the data in a set of (X, y, w, id) arrays.
  
  Parameters
  ----------
  X: np.ndarray
      Array of features
  y: np.ndarray
      Array of labels
  w: np.ndarray
      Array of weights.
  ids: np.ndarray
      Array of identifiers
  
  Returns
  -------
  Xtrans: np.ndarray
      Transformed array of features
  ytrans: np.ndarray
      Transformed array of labels
  wtrans: np.ndarray
      Transformed array of weights
  idtrans: np.ndarray
      Transformed array of identifiers
docstr_tok: ["Transform","the","data","in","a","set","of","(","X",",","y",",","w",",","id",")","arrays",".","Parameters","--","--","--","--","--","X",":","np.ndarray","Array","of","features","y",":","np.ndarray","Array","of","labels","w",":","np.ndarray","Array","of","weights",".","ids",":","np.ndarray","Array","of","identifiers","Returns","--","--","--","-","Xtrans",":","np.ndarray","Transformed","array","of","features","ytrans",":","np.ndarray","Transformed","array","of","labels","wtrans",":","np.ndarray","Transformed","array","of","weights","idtrans",":","np.ndarray","Transformed","array","of","identifiers"]
code: def transform_array(
      self, X: np.ndarray, y: np.ndarray, w: np.ndarray, ids: np.ndarray
  ) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
      """Transform the data in a set of (X, y, w, id) arrays.
  
      Parameters
      ----------
      X: np.ndarray
          Array of features
      y: np.ndarray
          Array of labels
      w: np.ndarray
          Array of weights.
      ids: np.ndarray
          Array of identifiers
  
      Returns
      -------
      Xtrans: np.ndarray
          Transformed array of features
      ytrans: np.ndarray
          Transformed array of labels
      wtrans: np.ndarray
          Transformed array of weights
      idtrans: np.ndarray
          Transformed array of identifiers
      """
      if not (
          len(y.shape) == 1 or (len(y.shape) == 2 and y.shape[1] == 1)
      ):
          raise ValueError("y must be of shape (N,) or (N, 1)")
      if not (
          len(w.shape) == 1 or (len(w.shape) == 2 and w.shape[1] == 1)
      ):
          raise ValueError("w must be of shape (N,) or (N, 1)")
      # Flattening is safe because of shape check above
      y = y.flatten()
      w = w.flatten()
      X_dups, y_dups, w_dups, ids_dups = [], [], [], []
      for i, c in enumerate(self.classes):
          duplication_ratio = self.duplication_ratio[i]
          c_inds = y == c
          X_c = X[c_inds]
          y_c = y[c_inds]
          w_c = w[c_inds]
          ids_c = ids[c_inds]
          X_c_dup = np.repeat(X_c, duplication_ratio, axis=0)
          y_c_dup = np.repeat(y_c, duplication_ratio, axis=0)
          w_c_dup = np.repeat(w_c, duplication_ratio, axis=0)
          ids_c_dup = np.repeat(ids_c, duplication_ratio, axis=0)
          X_dups.append(X_c_dup)
          y_dups.append(y_c_dup)
          w_dups.append(w_c_dup)
          ids_dups.append(ids_c_dup)
      Xtrans = np.concatenate(X_dups, axis=0)
      ytrans = np.concatenate(y_dups, axis=0)
      wtrans = np.concatenate(w_dups, axis=0)
      idstrans = np.concatenate(ids_dups, axis=0)
      return (Xtrans, ytrans, wtrans, idstrans)
  
file_path: deepchem/deepchem/trans/duplicate.py
imports: import logging
  import numpy
  from typing import Tuple
  from deepchem.data import Dataset
  from deepchem.trans.transformers import Transformer
label_desc: Use image node_id 2 for calling the DuplicateBalancingTransformer obj's underlying member method code with example usage: obj.transform_array(X, y, w, ids) and returns: Xtrans,  ytrans,  wtrans,  idstrans