def build(self, show_digits=2, show_bin_xy=False, add_totals=True):
        """Build the binning table.

        Parameters
        ----------
        show_digits : int, optional (default=2)
            The number of significant digits of the bin column.

        show_bin_xy: bool (default=False)
            Whether to show a single bin column with x and y.

        add_totals : bool (default=True)
            Whether to add a last row with totals.

        Returns
        -------
        binning_table : pandas.DataFrame
        """
        _check_build_parameters(show_digits, add_totals)

        if not isinstance(show_bin_xy, bool):
            raise TypeError("show_bin_xy must be a boolean; got {}."
                            .format(show_bin_xy))

        t_n_records = np.nansum(self.n_records)
        t_sum = np.nansum(self.sums)
        t_mean = t_sum / t_n_records
        p_records = self.n_records / t_n_records

        mask = (self.n_records > 0)
        self._mean = np.zeros(len(self.n_records))
        self._mean[mask] = self.sums[mask] / self.n_records[mask]

        # Compute divergence measure (continuous adaptation)
        woe = self._mean - t_mean
        iv = np.absolute(woe) * p_records
        t_iv = iv.sum()
        t_woe = np.absolute(woe).sum()

        self._iv = t_iv
        self._woe = t_woe
        self._t_mean = t_mean

        # Compute HHI
        self._hhi = hhi(p_records)
        self._hhi_norm = hhi(p_records, normalized=True)

        # Compute paths. This is required for both plot and analysis
        self._paths_x, self._paths_y = get_paths(self.m, self.n, self.P)

        if show_bin_xy:
            bin_xy_str = bin_xy_str_format(
                self.dtype_x, self.dtype_y, self.splits_x, self.splits_y,
                show_digits, self.categories_x, self.categories_y)

            bin_xy_str.extend(["Special", "Missing"])

            df = pd.DataFrame({
                "Bin": bin_xy_str,
                "Count": self.n_records,
                "Count (%)": p_records,
                "Sum": self.sums,
                "Std": self.stds,
                "Mean": self._mean,
                "WoE": woe,
                "IV": iv
                })

        else:
            bin_x_str = bin_str_format(
                self.dtype_x, self.splits_x, show_digits, self.categories_x)
            bin_y_str = bin_str_format(
                self.dtype_y, self.splits_y, show_digits, self.categories_y)

            bin_x_str.extend(["Special", "Missing"])
            bin_y_str.extend(["Special", "Missing"])

            df = pd.DataFrame({
                "Bin x": bin_x_str,
                "Bin y": bin_y_str,
                "Count": self.n_records,
                "Count (%)": p_records,
                "Sum": self.sums,
                "Std": self.stds,
                "Mean": self._mean,
                "WoE": woe,
                "IV": iv
                })

        if add_totals:
            if show_bin_xy:
                totals = ["", t_n_records, 1, t_sum, "", t_mean, t_woe, t_iv]
            else:
                totals = ["", "", t_n_records, 1, t_sum, "", t_mean, t_woe,
                          t_iv]
            df.loc["Totals"] = totals

        self._is_built = True

        return df
Build the binning table.

        Parameters
        ----------
        show_digits : int, optional (default=2)
            The number of significant digits of the bin column.

        show_bin_xy: bool (default=False)
            Whether to show a single bin column with x and y.

        add_totals : bool (default=True)
            Whether to add a last row with totals.

        Returns
        -------
        binning_table : pandas.DataFrame
        
optbinning/binning/multidimensional/binning_statistics_2d.py