docstr: Calculate sample sizes, for both under and oversampling.
  
  Parameters
  ----------
  p : int
      Number of positive instances in a group.
  n : int
      Number of negative instances in a group.
  target : float
      Target prevalence for the group.
  strategy : str
      Strategy to obtain the desired prevalence.
      Either "undersample" or "oversample".
  alpha : float
      Parameter that controls the new prevalence values. A value of 0 keeps
      original prevalence, and a value of 1 equalizes the prevalence.
  
  Returns
  -------
  tuple(int, int)
      The label to sample (negative or positive) and the number of samples
      to remove (undersampling) or add (oversampling).
code: def calculate_sample_sizes(
      self, p: int, n: int, target: float, strategy: str, alpha: float
  ) -> tuple[int, int]:
      """Calculate sample sizes, for both under and oversampling.
  
      Parameters
      ----------
      p : int
          Number of positive instances in a group.
      n : int
          Number of negative instances in a group.
      target : float
          Target prevalence for the group.
      strategy : str
          Strategy to obtain the desired prevalence.
          Either "undersample" or "oversample".
      alpha : float
          Parameter that controls the new prevalence values. A value of 0 keeps
          original prevalence, and a value of 1 equalizes the prevalence.
  
      Returns
      -------
      tuple(int, int)
          The label to sample (negative or positive) and the number of samples
          to remove (undersampling) or add (oversampling).
      """
      prevalence = p / (p + n)
      self.logger.debug(f"Calculated prevalence: {prevalence}")
      target = target * alpha + prevalence * (1 - alpha)
      self.logger.debug(f"Target prevalence: {target}")
      if strategy == "oversample":
          if prevalence < target:
              return 1, round(
                  (-p * target - n * target + p) / (target - 1)
              )
          else:
              return 0, round(p * ((1 / target) - 1) - n)
      elif strategy == "undersample":
          if prevalence < target:
              return 0, round((p * (1 - 1 / target)) + n)
          else:
              return 1, round(
                  (p * target + n * target - p) / (target - 1)
              )
      else:
          raise ValueError(
              f"Invalid strategy value. Try one of {STRATEGIES}."
          )
  
file_path: aequitas/src/aequitas/fairflow/methods/preprocessing/prevalence_sample.py
imports: from typing import Any, Optional
  import pandas
  from ...utils import create_logger
  from .preprocessing import PreProcessing
label_desc: Use image node_id 4 for calling the PrevalenceSampling obj's underlying member method code with example usage: obj.calculate_sample_sizes(p, n, target, strategy, alpha) and returns: int,  round, int,  round, int,  round, int,  round