Plotly bar widths inconsistency

Viewed 35

In plotly I am making various plots of the same, but I don't understand why in some subplots my bars are more narrow than in others. I make the subplots either via make_subplots() or via facet_row(), but the result is similar.

The bars in the middle and bottom chart are very narrow and slim if you look close enough. The code I use to generate them is simple:

 fig.add_trace(
            go.Bar(
                x=q.select("date").to_series(),
                y=q.select(metric).to_series()
            ),
            row=i+1,
            col=j+1,
        )
fig.show()

I have checked that the number of dates for each row is of the same orders of magnitude. Any tips?

enter image description here

UPDATE For a reproducible dataset refer to https://gist.github.com/KeremAslan/c20094b65c4023e8b1d8d6b70fe90f45.

The code used to generate the plot

import polars as pl

df = pl.read_csv("https://gist.githubusercontent.com/KeremAslan/c20094b65c4023e8b1d8d6b70fe90f45/raw/bcd44ed1c98ad7021c4b3951e3815d9b22a021a1/stackoverflow_plotly")

values = ["value_a", "value_b", "value_c", "value_d"]
groups = ["A", "B", "C", "D", ""]
fig = make_subplots(
    # rows=len(values),
    # cols=len(groups),
    rows=len(groups),
    cols=len(values),
    shared_xaxes=True,
    shared_yaxes=True
)

for group_index, group in enumerate(groups):
    for ix, value in enumerate(values):
        p = df.filter(pl.col("group") == group)
        fig.add_trace(
            go.Bar(
                x=df.select("date").to_series(),
                y=df.select(value).to_series()
            ),
            row=group_index+1,
            col=ix+1
        )

fig.update_layout(
    showlegend=False
)
fig.show()

1 Answers
  • I have not used polars before
  • two observations
    1. date is best passed to plotly as a date. Have used pandas to_datetime() to do this
    2. you series lengths are really too long for bar charts. Have sliced to first 20 records
  • bars are same width taking into account above points
import polars as pl
import pandas as pd
from plotly.subplots import make_subplots
import plotly.graph_objects as go

df = pl.read_csv(
    "https://gist.githubusercontent.com/KeremAslan/c20094b65c4023e8b1d8d6b70fe90f45/raw/bcd44ed1c98ad7021c4b3951e3815d9b22a021a1/stackoverflow_plotly"
)

values = ["value_a", "value_b", "value_c", "value_d"]
groups = ["A", "B", "C", "D", ""]

fig = make_subplots(
    # rows=len(values),
    # cols=len(groups),
    rows=len(groups),
    cols=len(values),
    shared_xaxes=True,
    shared_yaxes=True,
)

for group_index, group in enumerate(groups):
    for ix, value in enumerate(values):
        p = df.filter(pl.col("group") == group)
        fig.add_trace(
            go.Bar(
                x=pd.to_datetime(df.select("date").to_series())[0:20],
                y=df.select(value).to_series()[0:20],
            ),
            row=group_index + 1,
            col=ix + 1,
        )

fig.update_layout(showlegend=False)
fig.show()

enter image description here

heatmap visualisation

  • switched to pandas really
  • make range of x-axes consistent. Now everything shows.
import plotly.express as px
import polars as pl
from plotly.subplots import make_subplots

df = pl.read_csv(
    "https://gist.githubusercontent.com/KeremAslan/c20094b65c4023e8b1d8d6b70fe90f45/raw/bcd44ed1c98ad7021c4b3951e3815d9b22a021a1/stackoverflow_plotly"
)

df = df.with_column(pl.col("date").str.strptime(pl.Date).cast(pl.Datetime))

df2 = df.to_pandas().set_index(["group", "date"]).sort_index()

groups = df2.index.get_level_values(0).unique()

fig = make_subplots(rows=len(groups))

for i, g in enumerate(groups):
    fig.add_trace(
        px.imshow(df2.loc[g].T)
        .data[0]
        .update(
            hovertemplate=f"<b>{g}</b><br>"
            + "date: %{x}<br>y: %{y}<br>color: %{z}<extra></extra>"
        ),
        row=i + 1,
        col=1,
    )

rng = [
    df2.index.get_level_values(1).min().date(),
    df2.index.get_level_values(1).max().date(),
]

fig.for_each_xaxis(
    lambda ax: ax.update(range=rng, visible=ax.anchor == f"y{len(groups)}")
)
fig.for_each_yaxis(lambda ax: ax.update(visible=False))

enter image description here

Related