code: def discrete_ecdfer(
      df: pd.DataFrame,
      ascending: bool = True,
      prediction_column: str = "prediction",
      ecdf_column: str = "prediction_ecdf",
      max_range: int = 1000,
      round_method: Callable = int,
  ) -> LearnerReturnType:
      """
      Learns an Empirical Cumulative Distribution Function from the specified column
      in the input DataFrame. It is usually used in the prediction column to convert
      a predicted probability into a score from 0 to 1000.
  
      Parameters
      ----------
      df : Pandas' pandas.DataFrame
          A Pandas' DataFrame that must contain a `prediction_column` columns.
  
      ascending : bool
          Whether to compute an ascending ECDF or a descending one.
  
      prediction_column : str
          The name of the column in `df` to learn the ECDF from.
  
      ecdf_column : str
          The name of the new ECDF column added by this function.
  
      max_range : int
          The maximum value for the ECDF. It will go will go
           from 0 to max_range.
  
      round_method: Callable
          A function perform the round of transformed values for ex: (int, ceil, floor, round)
      """
  
      if ascending:
          base = 0
          sign = 1
      else:
          base = max_range
          sign = -1
  
      values = df[prediction_column]
  
      ecdf = ed.ECDF(values)
  
      df_ecdf = pd.DataFrame()
      df_ecdf["x"] = ecdf.x
      df_ecdf["y"] = pd.Series(base + sign * max_range * ecdf.y).apply(
          round_method
      )
  
      boundaries = (
          df_ecdf.groupby("y").agg((min, max))["x"]["min"].reset_index()
      )
  
      y = boundaries["y"]
      x = boundaries["min"]
      side = ecdf.side
  
      log = {
          "discrete_ecdfer": {
              "map": dict(zip(x, y)),
              "round_method": round_method,
              "nobs": len(values),
              "prediction_column": prediction_column,
              "ascending": ascending,
              "transformed_column": [ecdf_column],
          }
      }
  
      del ecdf
      del values
      del df_ecdf
  
      def p(new_df: pd.DataFrame) -> pd.DataFrame:
          if not ascending:
              tind = np.searchsorted(-x, -new_df[prediction_column])
          else:
              tind = (
                  np.searchsorted(x, new_df[prediction_column], side)
                  - 1
              )
  
          return new_df.assign(**{ecdf_column: y[tind].values})
  
      return p, p(df), log
  
imports: from typing import Any, Callable, Dict, List, Union, Optional
  import numpy
  import pandas
  from numpy import nan
  from sklearn.preprocessing import StandardScaler
  from statsmodels.distributions import empirical_distribution
  from toolz import curry, merge, compose, mapcat
  from fklearn.common_docstrings import learner_return_docstring, learner_pred_fn_docstring
  from fklearn.training.utils import log_learner_time
  from fklearn.types import LearnerReturnType, LearnerLogType
  from fklearn.preprocessing.schema import column_duplicatable
label_desc: Use image node_id 5 for calling a global function with example usage: discrete_ecdfer(df, ascending, prediction_column, ecdf_column, max_range, round_method) and returns: p,  p,  log, new_df