import plotly.graph_objects as go
fig=go.Figure()
cols=['NO2 mug/m^3','NO mug/m^3']
for idx,col in enumerate(cols):
for df in [ag,snd]:
fig.add_trace(go.Bar(x=df['Date'],y=df[col],
name=f'{str(df.Municipality.unique()[0])} {col}'))
#fig.add_trace(go.Bar(x=ag['Date'],y=ag['NO mug/m^3']))
fig.update_layout(barmode='group',xaxis=dict(title='Date'))
# print(df)
fig
In this snippet i take two columns (which are common in both dataframes) and use a bar chart which give me the following result
in this photo we get 4 distinct bars that do not overlay. what i want is to keep this format but to also add a second y axis. But because of the dynamic nature that this format will be used i want it to be versatile. When lets say we have one column ( NO mug/m^3) to not have the second axis.
i tried something like this
fig = go.Figure()
cols = ['NO2 mug/m^3', 'NO mug/m^3'] # Selected gases
dfs = [ag, snd] # List of dataframes
for df_idx, df in enumerate(dfs): # Iterate over DataFrames (locations)
for col_idx, col in enumerate(cols): # Iterate over gases
fig.add_trace(go.Bar(
x=df['Date'],
y=df[col],
name=f'{df.Municipality.unique()[0]} - {col}',
offsetgroup=str(df_idx), # Group bars per location
marker=dict(opacity=0.8),
yaxis="y" if col_idx == 0 else "y2" # Assign second gas to secondary y-axis
))
# Layout adjustments
layout_args = {
"barmode": "group", # Ensures bars are placed side-by-side
"xaxis": {"title": "Date"},
"legend_title": "Location - Gas"
}
if len(cols) == 1:
layout_args["yaxis"] = {"title": cols[0]} # Single Y-axis case
else:
layout_args["yaxis"] = {"title": cols[0]}
layout_args["yaxis2"] = {
"title": cols[1],
"overlaying": "y", # Overlay on primary y-axis
"side": "right",
"showgrid": False
}
fig.update_layout(**layout_args)
fig.show()
From what i tried i got something like the following
which is not desireable. is there any way to keep the format of my first image(4 distinct non overlaying bars per x point) while using some condition in order to achive my second axis?
thank for your patience
This is because you are using df_idx
to offset the bars. df_idx
will only be 0
or 1
.
You need to create another variable for offsetting the positions.
Example:
fig = go.Figure()
cols = ['NO2 mug/m^3', 'NO mug/m^3'] # Selected gases
dfs = [ag, snd] # List of dataframes
offsetgroup = 0 # new variable for offsetting position
for col_idx, col in enumerate(cols): # Iterate over gases
for df_idx, df in enumerate(dfs): # Iterate over DataFrames (locations)
fig.add_trace(go.Bar(
x=df['Date'],
y=df[col],
name=f'{df.Municipality.unique()[0]} - {col}',
offsetgroup=str(offsetgroup), # Group bars per location
marker=dict(opacity=0.8),
yaxis="y" if col_idx == 0 else "y2" # Assign second gas to secondary y-axis
))
offsetgroup += 1
# Layout adjustments
layout_args = {
"barmode": "group", # Ensures bars are placed side-by-side
"xaxis": {"title": "Date"},
"legend_title": "Location - Gas"
}
if len(cols) == 1:
layout_args["yaxis"] = {"title": cols[0]} # Single Y-axis case
else:
layout_args["yaxis"] = {"title": cols[0]}
layout_args["yaxis2"] = {
"title": cols[1],
"overlaying": "y", # Overlay on primary y-axis
"side": "right",
"showgrid": False
}
fig.update_layout(**layout_args)
fig.show()