docs: def impute_dataframe_range(df_impute, col_to_max, col_to_min, col_to_median):
      """
      Columnwise replaces all ``NaNs``, ``-inf`` and ``+inf`` from the DataFrame `df_impute` with average/extreme values
      from the provided dictionaries.
  
      This is done as follows: Each occurring ``inf`` or ``NaN`` in `df_impute` is replaced by
  
          * ``-inf`` -> by value in col_to_min
          * ``+inf`` -> by value in col_to_max
          * ``NaN`` -> by value in col_to_median
  
      If a column of df_impute is not found in the one of the dictionaries, this method will raise a ValueError.
      Also, if one of the values to replace is not finite a ValueError is returned
  
      This function modifies `df_impute` in place. Afterwards df_impute is
      guaranteed to not contain any non-finite values.
      Also, all columns will be guaranteed to be of type ``np.float64``.
  
      :param df_impute: DataFrame to impute
      :type df_impute: pandas.DataFrame
      :param col_to_max: Dictionary mapping column names to max values
      :type col_to_max: dict
      :param col_to_min: Dictionary mapping column names to min values
      :type col_to_max: dict
      :param col_to_median: Dictionary mapping column names to median values
      :type col_to_max: dict
  
      :return df_impute: imputed DataFrame
      :rtype df_impute: pandas.DataFrame
      :raise ValueError: if a column of df_impute is missing in col_to_max, col_to_min or col_to_median or a value
                         to replace is non finite
      """
      columns = df_impute.columns
  
      # Making sure col_to_median, col_to_max and col_to_min have entries for every column
      if not set(columns) <= set(col_to_median.keys()) or \
              not set(columns) <= set(col_to_max.keys()) or \
              not set(columns) <= set(col_to_min.keys()):
          raise ValueError("Some of the dictionaries col_to_median, col_to_max, col_to_min contains more or less keys "
                           "than the column names in df")
  
      # check if there are non finite values for the replacement
      if np.any(~np.isfinite(list(col_to_median.values()))) or \
              np.any(~np.isfinite(list(col_to_min.values()))) or \
              np.any(~np.isfinite(list(col_to_max.values()))):
          raise ValueError("Some of the dictionaries col_to_median, col_to_max, col_to_min contains non finite values "
                           "to replace")
  
      # Make the replacement dataframes as large as the real one
      col_to_max = pd.DataFrame([col_to_max]*len(df_impute), index=df_impute.index)
      col_to_min = pd.DataFrame([col_to_min]*len(df_impute), index=df_impute.index)
      col_to_median = pd.DataFrame([col_to_median]*len(df_impute), index=df_impute.index)
  
      df_impute.where(df_impute.values != np.PINF, other=col_to_max, inplace=True)
      df_impute.where(df_impute.values != np.NINF, other=col_to_min, inplace=True)
      df_impute.where(~np.isnan(df_impute.values), other=col_to_median, inplace=True)
  
      df_impute.astype(np.float64, copy=False)
      return df_impute