"""Create a dual distribution visualization of the desired column in a `DataFrame`. A histogram shows the distribution of observations, and bottom chart displays them all showing their cumulative distribution. Optionally, you can set `hover_name` to show the actual value of each observation on hover."""

# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/08_ecdf.ipynb.

# %% auto 0
__all__ = ['ecdf']

# %% ../nbs/08_ecdf.ipynb 4
import pandas as pd
import plotly.express as px

# %% ../nbs/08_ecdf.ipynb 6
def ecdf(
    df,
    x,
    hover_name=None,
    title=None,
    subtitle=None,
    height=None,
    width=None,
    template=None,
    **kwargs,
):
    """
    Create an empirical cumulative distribution chart, a thin wrapper around px.ecdf.

    Parameters
    ----------
    df : pandas.DataFrame
        A DataFrame from which you want to visualize one of the columns' distribution.
    x : str
        The name of the column to visualize.
    hover_name : str
        The name of the column to use for labeling the markers on mouseover.
    title : str
        The title of the chart.
    subtitle : str
        The subtitle of the chart.
    height : int
        The height of the chart in pixels.
    width : int
        The width of the chart in pixels.

    Returns
    -------
    ecdf : plotly.graph_objects.Figure
        A plotly chart of the desired ecdf.
    """
    df = df.sort_values(x)
    df["count below"] = range(len(df))
    df["count above"] = range(len(df) - 1, -1, -1)
    df["total count"] = len(df)
    hover_data = [
        "count below",
        "count above",
        "total count",
        hover_name,
        "cum. sum",
        "cum. perc",
    ]
    try:
        df["cum. sum"] = df[x].cumsum()
        df["cum. perc"] = df[x].cumsum().div(df[x].sum())
        hovertemplate_suffix = (
            "<b>Values:</b><br>"
            + "cumulative sum: %{customdata[4]:,}<br>"
            + "cumulative percentage: %{customdata[5]:.1%}"
        )
    except TypeError:
        hover_data = hover_data[:-2]
        hovertemplate_suffix = ""
    cdf = [x / len(df) for x in range(1, len(df) + 1)]
    cumsum = 0
    fig = px.ecdf(
        df.dropna(subset=[x]),
        x=x,
        lines=False,
        markers=True,
        category_orders={x: df.sort_values(x)[x]},
        marginal="histogram",
        hover_name=hover_name,
        title=title,
        subtitle=subtitle,
        height=height,
        width=width,
        hover_data=hover_data,
        ecdfnorm="percent",
        template=template,
        **kwargs,
    )
    # fig.data[0].hovertemplate = '%{customdata[3]}' + f'<b>{x.replace("_", " ").title()}</b><br><br>{x}' + ': %{x}<br>percent: %{y}<br><br>count below: %{customdata[0]:,}<br>count above: %{customdata[1]:,}<br>total count: %{customdata[2]:,}<extra></extra>'
    for data in fig.data:
        if data.type == "histogram":
            data.opacity = 1
            continue
        if data.type in ["scatter", "scattergl"]:
            data.y = cdf[cumsum : cumsum + len(data.y)]
            cumsum += len(data.y)
            data.marker.symbol = "circle-open"
            data.marker.size = 11
            prefix = "<b>%{customdata[3]}</b>" if hover_name is not None else ""
            data.hovertemplate = (
                prefix
                + f"<br><br>{x}:"
                + " %{x}<br><br>"
                + "<b>Counts:</b><br>"
                + "percent: %{y:.1%}<br>"
                + "count below: %{customdata[0]:,}<br>"
                + "count above: %{customdata[1]:,}<br>"
                + "total count: %{customdata[2]:,}<br><br>"
                + hovertemplate_suffix
                + "<extra></extra>"
            )
    # fig.update_yaxes(ticksuffix='%', showspikes=True)
    fig.update_yaxes(showspikes=True, tickformat=".0%")
    fig.layout.yaxis2.tickformat = ",.0f"
    fig.update_xaxes(showspikes=True)
    if fig.data[-1].type == "histogram":
        fig.layout.yaxis2.showspikes = False
        fig.layout.xaxis2.showspikes = False
        fig.layout.yaxis2.ticksuffix = ""
        fig.layout.yaxis2.showticklabels = True
        fig.layout.yaxis2.title = "count"
    return fig
