docs: def accounting_sample_replace(total, data, accounting_column, prob_column=None, max_iterations=50):
      """
      Sample rows with accounting with replacement.
  
      Parameters
      ----------
      total : int
          The control total the sampled rows will attempt to match.
      data: pandas.DataFrame
          Table to sample from.
      accounting_column: string
          Name of column with accounting totals/quantities to apply towards the control.
      prob_column: string, optional, default None
          Name of the column in the data to provide probabilities or weights.
      max_iterations: int, optional, default 50
          When using an accounting attribute, the maximum number of sampling iterations
          that will be applied.
  
      Returns
      -------
      sample_rows : pandas.DataFrame
          Table containing the sample.
      matched: bool
          Indicates if the total was matched exactly.
  
      """
      # check for probabilities
      p = get_probs(data, prob_column)
  
      # determine avg number of accounting items per sample (e.g. persons per household)
      per_sample = data[accounting_column].sum() / (1.0 * len(data.index.values))
  
      curr_total = 0
      remaining = total
      sample_rows = pd.DataFrame()
      closest = None
      closest_remain = total
      matched = False
  
      for i in range(0, max_iterations):
  
          # stop if we've hit the control
          if remaining == 0:
              matched = True
              break
  
          # if sampling with probabilities, re-caclc the # of items per sample
          # after the initial sample, this way the sample size reflects the probabilities
          if p is not None and i == 1:
              per_sample = sample_rows[accounting_column].sum() / (1.0 * len(sample_rows))
  
          # update the sample
          num_samples = int(math.ceil(math.fabs(remaining) / per_sample))
  
          if remaining > 0:
              # we're short, add to the sample
              curr_ids = np.random.choice(data.index.values, num_samples, p=p)
              sample_rows = pd.concat([sample_rows, data.loc[curr_ids]])
          else:
              # we've overshot, remove from existing samples (FIFO)
              sample_rows = sample_rows.iloc[num_samples:].copy()
  
          # update the total and check for the closest result
          curr_total = sample_rows[accounting_column].sum()
          remaining = total - curr_total
  
          if abs(remaining) < closest_remain:
              closest_remain = abs(remaining)
              closest = sample_rows
  
      return closest, matched