I have 2 graphs with the solution I require existing somewhere between the two graphs.
Example data:
hour PRODUCT_NAME LOTS hex_with_transparency
523 08:00 Propane FEI -12 #30a2da80
136 09:00 Brent (Fut) 4 #fc4f30FF
527 09:00 Brent (Fut) -207 #fc4f3080
I need to create a plot with positive/negative trades plotted in the same bar, with the negative volume being less opaque, with grouping around the same hours.
The first plot I have creates a legend based on the rgb colours of my data to prevent making the legend include the various rgba less opaque products, and I do this by creating a trace per df row, then adding some formatting. The issue is, apart from offsetting the hour data around each hour for each product, I am not sure if there are any bult-in arguments.
Code for plot 1:
five_thirty_eight_colors = [
β#30a2daβ, β#fc4f30β, β#e5ae38β, β#6d904fβ, β#8b8b8bβ, β#b96db8β, β#ff9e27β, # Original colors
β#1f77b4β, β#d62728β, β#9467bdβ, β#2ca02cβ, β#bcbd22β, β#17becfβ, β#ff7f0eβ, # Extra contrasting colors
β#ff6347β, β#9370dbβ, β#3cb371β, β#f4a460β, β#4682b4β, β#daa520β, β#ff4500β # Additional harmonious colors
]
unique_products = df_quantity[βPRODUCT_NAMEβ].unique()
# probably need more colours
product_colors = {product: five_thirty_eight_colors[i % len(five_thirty_eight_colors)] for i, product in
enumerate(unique_products)}
df_quantity["hex_with_transparency"] = df_quantity.apply(
lambda x:
add_opacity_to_hex_colours(product_colors[x["PRODUCT_NAME"]], 100)
if x["LOTS"] > 0
else add_opacity_to_hex_colours(product_colors[x["PRODUCT_NAME"]], 50),
axis=1)
df_quantity["rgba"] = df_quantity["hex_with_transparency"].apply(hex_colours_to_rbga)
fig_quan_tran = go.Figure()
for product in unique_products:
rgb_color = product_colors[product] # Get RGB color for the product
fig_quan_tran.add_trace(go.Bar(
x=[None],
y=[None],
name=product,
marker_color=rgb_color,
showlegend=True,
width=0,
))
for _, row in df_quantity.iterrows():
fig_quan_tran.add_trace(go.Bar(
x=[row['hour']],
y=[row['LOTS']],
name=row['PRODUCT_NAME'],
marker_color=row['rgba'],
showlegend=False,
hovertemplate=f"{row['PRODUCT_NAME']}<br>LOTS: {row['LOTS']}<br>Hour: {row['hour']}<extra></extra>",
))
fig_quan_tran.update_layout(
title="Trade Actions",
xaxis_title="Hour",
yaxis_title="LOTS",
xaxis=dict(
type='category',
),
legend_title="Product Name",
barmode='group', # Ensure bars are displayed side-by-side by hour without stacking
bargap=0, # Remove spacing between bars
bargroupgap=0.1,
margin={"pad": 0},
width=1000
)
this produces this:
the other data is a multicatgeory but I cannot seem to resolve the legend:
x = [
df_quantity['hour'],
df_quantity['PRODUCT_NAME']
]
fig_quan_tran_1 = go.Figure()
fig_quan_tran_1.add_bar(x=x, y=df_quantity['LOTS'])
fig_quan_tran_1.data[0].marker.color = df_quantity['rgba']
fig_quan_tran_1.update_layout(height=800,
margin=dict(b=250)
)
which generates the following graph:
but I want the legend to have the products and want only the hours at the bottom.
ignoring the hex->hex with opacity β rgba, which I will resolve, are there any easily configurable layout settings to resolve my issue?
Main reason for the legend is the streamlit functionality that make sit easier for a user to read/understand the data