Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Marimekko aka Mekko plot #4019

Closed
nicolaskruchten opened this issue Jul 5, 2019 · 4 comments
Closed

Marimekko aka Mekko plot #4019

nicolaskruchten opened this issue Jul 5, 2019 · 4 comments

Comments

@nicolaskruchten
Copy link
Contributor

nicolaskruchten commented Jul 5, 2019

Placeholder issue for discussing the addition of this kind of trace. See also #2901 for a circular variant, #4020 for the more-than-two-level variant and #1038 for the general-purpose treemap variant.

Here's a representative example of what this could look like:

image

Note that this is quite bar-like with two continuous axes, but also has non-linear category labels above.

This one doesn't have a (visible) continuous x-axis:

image

@eddy-geek
Copy link

eddy-geek commented Apr 9, 2020

Here is an implementation based on @nicolaskruchten work on #4461 :

def stacked_bar_width_plot(df, value_cols, width_col, colors=None, **subplot):
    """A stacked column plot with variable bar width.
       :param df
       :param list value_cols: columns of `df`, already normalized (sum=1 for every line).
       :param str width_col: column of `df`, unbounded, used (i) as label (ii) to compute width.
       :param dict subplot: optional figure/row/col
    """
    categories = df.index.to_list()
    width = df[width_col]
    htmpl = width_col + ': %{customdata}, %{y}'
    x = np.cumsum([0] + list(width[:-1]))
    colors = colors or [None, ] * len(value_cols)

    figure = subplot.pop('figure', go.Figure())
    for colname, color in zip(value_cols, colors):
        figure.add_trace(go.Bar(name=colname, x=x, y=df[colname], width=width, hovertemplate=htmpl, customdata=width, offset=0, marker_color=color), **subplot)
    return figure.update_xaxes(
        tickvals=x + np.array(width) / 2,
        ticktext=categories,
        range=[0, np.sum(width)], **subplot
    ) \
        .update_yaxes(tickformat=',.0%', range=[0, 1], row=subplot.get('row'), col=subplot.get('col')) \
        .update_layout(barmode='stack', bargap=0)


def mekko_plot(df, unit_name=None, colors=None, **subplot):
    """A mekko plot is a normalized stacked column plot with variable bar width.

       :param DataFrame df: already indexed by category, with only numeric columns:
                   there will be one stacked-bar per line (X), labeled after the index, with one bar per column.
       :param str unit_name: used to populate hover.
       :param list colors: color of each column. None for default palette (blue, red, ...).
       The rest (title..) is easily added afterwards.
    """
    # Normalize then defer to stacked_bar_width_plot plot.
    value_cols = df.columns
    w = pd.DataFrame({unit_name: df.sum(axis='columns')})
    w[value_cols] = df.div(w[unit_name], axis='index')

    return stacked_bar_width_plot(w, value_cols, width_col=unit_name, colors=colors, **subplot)

# Example
df = pd.DataFrame(dict(category=['a','a', 'b',  'b', 'a','a', 'b',  'b'],
                       var1=[9,2,5,3,2,4,6,0],
                       var2=[1,2,3,4,2,6,7,8])).set_index('category')
display(df)
mekko_plot(df, unit_name='some_label', colors=['blue', 'red'])

Display:
image

@prodigeek
Copy link

Is there a way to assign a single color to a column in this code? I have a large mekko with many individual stacks - I'd rather have each column have a single color. Any suggestions?
Thanks!

@vpobleteacustica
Copy link

Many thanks, great job!

@gvwilson
Copy link
Contributor

Hi - we are trying to tidy up the stale issues and PRs in Plotly's public repositories so that we can focus on things that are still important to our community. Since this one has been sitting for several years, I'm going to close it; if it is still a concern, please add a comment letting us know what recent version of our software you've checked it with so that I can reopen it and add it to our backlog. Thanks for your help - @gvwilson

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants