Create a combination of “relative” and “grouped” chart in Python

你。 提交于 2021-01-29 12:51:10

问题


I need to create a combination of "relative" and "grouped" chart in plotly.

I figured out how to create stacked and grouped by using this code:

from plotly import graph_objects as go
import plotly

pyplt = plotly.offline.plot

data = {
    "Sports_19": [15, 23, 32, 10, 23, 22, 32, 24],
    "Casual_19": [4, 12, 11, 14, 15, 12, 22, 14],
    "Yoga_19": [4, 8, 18, 6, 12, 11, 10, 4],
    "Sports_20": [11, 18, 18, 0, 20, 12, 12, 11],
    "Casual_20": [20, 10, 9, 6, 10, 11, 17, 22],
    "Yoga_20": [11, 18, 18, 0, 20, 12, 12, 11],
    "labels": ["January", "February", "March", "April", "May", 'June', 'July', "August"]
    
}

fig = go.Figure()
fig.add_trace(go.Bar(name="Sports",x=data["labels"],y=data["Sports_19"],offsetgroup=19,marker_color='lightsalmon',text=data["Sports_19"],textposition='auto'))
fig.add_trace(go.Bar(name="Casual",x=data['labels'],y=data['Casual_19'],offsetgroup=19,base=data['Sports_19'],marker_color='crimson',text=data["Casual_19"],textposition='auto'))
fig.add_trace(go.Bar(name="Yoga",x=data['labels'],y=data['Yoga_19'],marker_color='indianred',text=data["Yoga_19"],textposition='auto',offsetgroup=19,base=[val1 + val2 for val1, val2 in zip(data["Sports_19"], data["Casual_19"])]))
fig.add_trace(go.Bar(name="Sports_20",x=data["labels"],y=data["Sports_20"],offsetgroup=20,marker_color='lightsalmon',showlegend=False,text=data["Sports_20"],textposition='auto'))
fig.add_trace(go.Bar(name="Casual_20",x=data['labels'],y=data['Casual_20'],offsetgroup=20,base=data['Sports_20'],marker_color='crimson',showlegend=False,text=data["Casual_20"],textposition='auto'))
fig.add_trace(go.Bar(name="Yoga_20", x=data['labels'], y=data['Yoga_20'], marker_color='indianred', text=data["Yoga_20"], showlegend=False, textposition='auto', offsetgroup=20, base=[val1 + val2 for val1, val2 in zip(data["Sports_20"], data["Casual_20"])]))

fig.update_layout(title="2019 vs 2020 Sales by Category",yaxis_title="Sales amount in US$")

fig.show()
pyplt(fig, auto_open=True)

Output is this:

Is there is any way i can convert this graph to combination of "relative" and "grouped"? May be not with plotly, but with matplotlib or another tools?

p.s. Here is the example of "relative graph"(but its not grouped):


回答1:


Probably the most straightforward way is to create two new dataframes df_perc_19 and df_perc_20 to store your data, normalized to relative percentages for each month in each year, rounding off to two digits using .round(2) since a long decimal will cause the default direction of the text to change - feel free to adjust this however you like.

Then access the values in these new dataframes for your traces, and although it's ugly, you can get percentages to display for the text parameter using something like: text=[str(x)+"%" for x in df_perc_19["Casual_19"]]

import pandas as pd
import plotly
from plotly import graph_objects as go

# pyplt = plotly.offline.plot

data = {
    "Sports_19": [15, 23, 32, 10, 23, 22, 32, 24],
    "Casual_19": [4, 12, 11, 14, 15, 12, 22, 14],
    "Yoga_19": [4, 8, 18, 6, 12, 11, 10, 4],
    "Sports_20": [11, 18, 18, 0, 20, 12, 12, 11],
    "Casual_20": [20, 10, 9, 6, 10, 11, 17, 22],
    "Yoga_20": [11, 18, 18, 0, 20, 12, 12, 11],
    # "labels": ["January", "February", "March", "April", "May", 'June', 'July', "August"]
    
}

labels = ["January", "February", "March", "April", "May", 'June', 'July', "August"]
df = pd.DataFrame(data=data,index=labels)
## normalize data for the months of 2019, and the months of 2020
df_perc_19 = df.apply(lambda x: 100*x[["Sports_19","Casual_19","Yoga_19"]] / x[["Sports_19","Casual_19","Yoga_19"]].sum(),axis=1).round(2)
df_perc_20 = df.apply(lambda x: 100*x[["Sports_20","Casual_20","Yoga_20"]] / x[["Sports_20","Casual_20","Yoga_20"]].sum(),axis=1).round(2)

fig = go.Figure()
## traces for 2019
fig.add_trace(go.Bar(name="Sports",x=labels,y=df_perc_19["Sports_19"],offsetgroup=19,marker_color='lightsalmon',text=[str(x)+"%" for x in df_perc_19["Sports_19"]],textposition='auto'))
fig.add_trace(go.Bar(name="Casual",x=labels,y=df_perc_19['Casual_19'],offsetgroup=19,base=df_perc_19['Sports_19'],marker_color='crimson',text=[str(x)+"%" for x in df_perc_19["Casual_19"]],textposition='auto'))
fig.add_trace(go.Bar(name="Yoga",x=labels,y=df_perc_19['Yoga_19'],marker_color='indianred',text=[str(x)+"%" for x in df_perc_19["Yoga_19"]],textposition='auto',offsetgroup=19,base=[val1 + val2 for val1, val2 in zip(df_perc_19["Sports_19"], df_perc_19["Casual_19"])]))
## traces for 2020
fig.add_trace(go.Bar(name="Sports_20",x=labels,y=df_perc_20["Sports_20"],offsetgroup=20,marker_color='lightsalmon',showlegend=False,text=[str(x)+"%" for x in df_perc_20["Sports_20"]] ,textposition='auto'))
fig.add_trace(go.Bar(name="Casual_20",x=labels,y=df_perc_20['Casual_20'],offsetgroup=20,base=df_perc_20['Sports_20'],marker_color='crimson',showlegend=False,text=[str(x)+"%" for x in df_perc_20["Casual_20"]],textposition='auto'))
fig.add_trace(go.Bar(name="Yoga_20", x=labels, y=df_perc_20['Yoga_20'], marker_color='indianred', text=[str(x)+"%" for x in df_perc_20["Yoga_20"]], showlegend=False, textposition='auto', offsetgroup=20, base=[val1 + val2 for val1, val2 in zip(df_perc_20["Sports_20"], df_perc_20["Casual_20"])]))

fig.update_layout(title="2019 vs 2020 Sales by Category",yaxis_title="Sales amount in US$ (percentage)")

fig.show()
# pyplt(fig, auto_open=True)



来源:https://stackoverflow.com/questions/63772597/create-a-combination-of-relative-and-grouped-chart-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!