Skip to content

add stacked grouped bars #4914

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

Closed
nicolaskruchten opened this issue Jun 10, 2020 · 17 comments
Closed

add stacked grouped bars #4914

nicolaskruchten opened this issue Jun 10, 2020 · 17 comments
Assignees
Labels
feature something new P3 backlog

Comments

@nicolaskruchten
Copy link
Contributor

nicolaskruchten commented Jun 10, 2020

We need to permit mixed stacked and grouped bars.

We will implement this with a new bar.stackgroup attribute as spec'ed here: #3402

@nicolaskruchten
Copy link
Contributor Author

nicolaskruchten commented Jun 10, 2020

See also related #3614, #1835, #1015. I'd like to keep the current issue as the master tracking one for this work, so we can close out others and refer to this one as needed.

@nicolaskruchten nicolaskruchten removed this from the v1.58.0 milestone Jul 7, 2020
@baumstan
Copy link

I see this issue is marked as closed but I'm having trouble tracking resolution. Could you point me in the right direction, please?

See also related #3614, #1835, #1015. I'd like to keep the current issue as the master tracking one for this work, so we can close out others and refer to this one as needed.

@nicolaskruchten
Copy link
Contributor Author

This issue is actually still open :)

@valentinstn
Copy link

Is there any update on this issue?

@nicolaskruchten
Copy link
Contributor Author

This issue is going to be worked on in the next couple of months.

@valentinstn
Copy link

Thanks @nicolaskruchten

@anyadmitrieva
Copy link

Hello, could you please tell me if this feature is still expected to be available soon?

@nicolaskruchten
Copy link
Contributor Author

We will be working on it in the near future but I can't publicly commit to a timeline at this time.

@tanya-pix
Copy link

tanya-pix commented Jun 17, 2021

We will be working on it in the near future but I can't publicly commit to a timeline at this time.

Are there any updates on this?

@RenaudLN
Copy link

For anyone trying to do this, whilst waiting for the official feature you can get the same outcome by creating the second stackgroup on another yaxis and playing with the traces offsets.
image

@araichev
Copy link

araichev commented Oct 17, 2021

@RenaudLN or anyone else, can you show us code to produce the figure above or similar?

@Alexander-Serov
Copy link

@RenaudLN Yes, could you please share the code for your plot?

@RenaudLN
Copy link

RenaudLN commented Feb 7, 2022

@araichev @Alexander-Serov Here is a minimum reproducible example with Python. Note that the offsets are suited to this monthly data and will have to be adjusted with other inputs.

import numpy as np
import pandas as pd
import plotly.graph_objects as go


# Create dummy data indexed by month and with multi-columns [product, revenue]
index = pd.date_range("2020", "2021", freq="MS", closed="left")
df = pd.concat(
    [
        pd.DataFrame(
            np.random.rand(12, 3) * 1.25 + 0.25,
            index=index,
            columns=["Revenue1", "Revenue2", "Revenue3"]
        ),
        pd.DataFrame(
            np.random.rand(12, 3) + 0.5,
            index=index,
            columns=["Revenue1", "Revenue2", "Revenue3"]
        ),
    ],
    axis=1,
    keys=["Product1", "Product2"]
)

# Create a figure with the right layout
fig = go.Figure(
    layout=go.Layout(
        height=600,
        width=1000,
        barmode="relative",
        yaxis_showticklabels=False,
        yaxis_showgrid=False,
        yaxis_range=[0, df.groupby(axis=1, level=0).sum().max().max() * 1.5],
       # Secondary y-axis overlayed on the primary one and not visible
        yaxis2=go.layout.YAxis(
            visible=False,
            matches="y",
            overlaying="y",
            anchor="x",
        ),
        font=dict(size=24),
        legend_x=0,
        legend_y=1,
        legend_orientation="h",
        hovermode="x",
        margin=dict(b=0,t=10,l=0,r=10)
    )
)

# Define some colors for the product, revenue pairs
colors = {
    "Product1": {
        "Revenue1": "#F28F1D",
        "Revenue2": "#F6C619",
        "Revenue3": "#FADD75",
    },
    "Product2": {
        "Revenue1": "#2B6045",
        "Revenue2": "#5EB88A",
        "Revenue3": "#9ED4B9",
    }
}

# Add the traces
for i, t in enumerate(colors):
    for j, col in enumerate(df[t].columns):
        if (df[t][col] == 0).all():
            continue
        fig.add_bar(
            x=df.index,
            y=df[t][col],
            # Set the right yaxis depending on the selected product (from enumerate)
            yaxis=f"y{i + 1}",
            # Offset the bar trace, offset needs to match the width
            # The values here are in milliseconds, 1billion ms is ~1/3 month
            offsetgroup=str(i),
            offset=(i - 1) * 1000000000,
            width=1000000000,
            legendgroup=t,
            legendgrouptitle_text=t,
            name=col,
            marker_color=colors[t][col],
            marker_line=dict(width=2, color="#333"),
            hovertemplate="%{y}<extra></extra>"
        )

fig.show()

image

@lyndon-bird
Copy link

Is there any update with this issue? Would be great to have implemented!

@gusblack-tt
Copy link

Is there any update on this feature? Looks like it has been asked for in one form or another for 8 years

@clarson0
Copy link

clarson0 commented May 7, 2024

@araichev Is this different than multicategory? I recently made a similar chart to the screenshot above

`function onlyUnique(value, index, array) {
return array.indexOf(value) === index;
}

// Example data for the x-axis, normally you would fetch this from your data set
var categories = [
["2023-12-01", "Dog"], ["2023-12-02", "Cat"], ["2023-12-03", "Mouse"],
["2023-12-04", "Dog"], ["2023-12-05", "Cat"], ["2023-12-06", "Mouse"],
["2023-12-07", "Dog"], ["2023-12-08", "Cat"], ["2023-12-09", "Mouse"]
];

let dates = categories.map(c => {
return c[0];
})

let animals = categories.map(c => {
return c[1]
})

dates = dates.filter(onlyUnique);
animals = animals.filter(onlyUnique);

let xDates = [];
dates.forEach(d => {
animals.forEach(c => {
xDates.push(d);
})
})

let xAnimals = [];
dates.forEach(d => {
animals.forEach(c => {
xAnimals.push(c);
})
})

var yValuesA = xAnimals.map(() => Math.random() * 0.95 + 0.05);
var yValuesB = xAnimals.map(() => Math.random() * 0.95 + 0.05);

var data = [
{
"marker": {
"color": [
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)",
"rgb(25, 80, 22)",
"rgb(15, 60, 90)",
"rgb(113, 13, 14)",
"rgb(127, 63, 0)"
],
"opacity": 0.5
},
"name": "Test data A",
"showlegend": false,
"type": "bar",
"x": [
xDates,
xAnimals
],
"y": yValuesA,
},
{
"marker": {
"color": 'darkblue',
"opacity": 0.5
},
"name": "Test data B",
"showlegend": false,
"type": "bar",
"x": [
xDates,
xAnimals
],
"y": yValuesB,
},
];

var layout = {
paper_bgcolor: "lightblue",
plot_bgcolor: "lightgrey",
margin: {
"t": 20,
"r": 20,
"b": 120,
"l": 20,
// "pad": 0
},
barmode: "stack",
xaxis: {
"anchor": "y",
"type": "multicategory",
"tickangle": "auto",
"autotickangles": [
90
],
"tickfont": {
"size": 9
},
"showdividers": true,
"tickson": "boundaries",
"ticklen": 14,
"dividercolor": "grey",
"dividerwidth": 1,
"range": [
-0.5,
83.5
],
"autorange": true
},
yaxis: {
type: 'linear',
range: [0,1],
}
}

// console.log('data', data);
// console.log('layout', layout);
// console.log('xDates', xDates);
// console.log('xAnimals', xAnimals)

Plotly.newPlot('myDiv', data, layout);`

Screenshot 2024-05-07 at 2 15 39 PM

@gvwilson gvwilson removed the sponsored label Aug 8, 2024
@gvwilson gvwilson changed the title Stacked grouped bars add stacked grouped bars Aug 9, 2024
@gvwilson gvwilson added the P3 backlog label Aug 9, 2024
@archmoj
Copy link
Contributor

archmoj commented Nov 8, 2024

Resolved in #7009.

@archmoj archmoj closed this as completed Nov 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature something new P3 backlog
Projects
None yet
Development

No branches or pull requests