admin管理员组

文章数量:1402041

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

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

Share Improve this question asked Mar 21 at 14:50 savvas pehlivanidissavvas pehlivanidis 815 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 3

This is because you are using df_idx to offset the bars. df_idx will only be 0 or 1.

When multiple data sets (traces) share a common x-axis (for vertical bars) or y-axis (for horizontal bars), the offsetgroup property allows you to align bars at the same position. Assigning the different offsetgroup value to these traces instructs Plotly to treat them as a different groups for offsetting, ensuring bars with matching coordinates don't overlay.

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()

本文标签: pandasPlotly bar conditional dual axis pythonStack Overflow