I'm trying to create a chart, that looks like a Ridgeplot (for examples see this and this), but has smoothed Area charts with a categorical x-axis as a basis.

Why standard Ridgeplot libraries don't work: Ridgeplots are usually used to display densities, which means you have a numerical x-axis. That's why in Plotly ridgeplots are considered as a variation of a violin plot.

Do you have any suggestions how this could be implemented?

4 Replies 4

Your question is very unclear. Please try to make up test data that better illustrate how your values look like. Your x-values are non-numerical, where smoothing out the plot creates confusion. Do the x-values have a strict ordering? Mixing up ridgeplots, area plots and violin plots adds even more confusion.

Seaborn's ridge plot examples can be easily adapted to curves that aren't related to densities. However, note that to create a good-looking ridge plot a lot of testing and tweeking is needed. As such, a general example won't really help you a lot if your data looks just a little bit different.

Maybe you should divide your question into steps. First, try to make a nice "smooth" plot for just one curve that fits your data.

here are some clarifications for this request:

Step1: Data

Let's assume you have a factory that produces 3 products (A,B,C). Each product goes through 3 production steps (Stamping, Assembly, Test). You measure for each product the cycle time per production step in minutes. The data looks like this:

products=['Product A', 'Product A','Product A','Product A','Product A','Product B','Product B','Product B','Product B','Product B', 'Product C','Product C','Product C','Product C','Product C']

production_step=['Start', 'Stamping', 'Assembly','Test','End','Start', 'Stamping', 'Assembly','Test','End','Start', 'Stamping', 'Assembly','Test','End','Start', 'Stamping', 'Assembly','Test','End','Start', 'Stamping', 'Assembly','Test','End']

cycle_time=[0,150,100,170,0,0,130,80,100,0,0,100,90,120,0]

data = list(zip(products, production_step, cycle_time))

df=pd.DataFrame(data, columns=['Product', 'Production Step', 'Cycle Time (min)'])

Note: I artificially added a "Start" and "End" time of 0 so the area charts in the next Step 2 resemble density plots.

Step 2: Visualization

fig=go.Figure()

fig.add_trace(go.Scatter(x=df["Production Step"], y=df["Cycle Time (min)"], line_shape='spline', fill='tozeroy'))

fig.show()

enter image description here Note:

  • line_shape='spline' makes the line chart look smooth.
  • fill='tozeroy' fills the the area below the line to the x-axis, which turns the line chart to an area plot.

Step3: Make it look like a Ridgeplot

Ridgeplot example from the internet for reference:

enter image description here This is where I'm stuck. What is missing is a vertical offset and the Product names appearing along the y-axis.

Do you have any ideas how to make this happen?

This can be done with Altair:

enter image description here

import altair as alt
import polars as pl

df = pl.DataFrame(
    dict(
        products=[
            "Product A",
            "Product A",
            "Product A",
            "Product A",
            "Product A",
            "Product B",
            "Product B",
            "Product B",
            "Product B",
            "Product B",
            "Product C",
            "Product C",
            "Product C",
            "Product C",
            "Product C",
        ],
        production_step=[
            "Start",
            "Stamping",
            "Assembly",
            "Test",
            "End",
            "Start",
            "Stamping",
            "Assembly",
            "Test",
            "End",
            "Start",
            "Stamping",
            "Assembly",
            "Test",
            "End",
        ],
        cycle_time=[
            0,
            150,
            100,
            170,
            0,
            0,
            130,
            80,
            100,
            0,
            0,
            100,
            90,
            120,
            0,
        ],
    )
)

step = 50
overlap = 2

alt.Chart(df).mark_area(interpolate="monotone").encode(
    alt.X(
        "production_step",
        sort=["Start", "Stamping", "Assembly", "Test", "End"],
    ).axis(labelAngle=-45),
    alt.Y("cycle_time").axis(False).scale(range=[step, -step * overlap]),
    alt.Row("products", title="").header(labelAngle=0, labelAlign="left"),
    alt.Color("products"),
).properties(width=400, height=50, bounds="flush").configure_facet(
    spacing=0
).configure_view(stroke=None).configure_title(anchor="end")

Thanks @kgoodrick, your answer works perfectly. Just one addition: I had to change axis(False) to axis(None) for it to work. If you post it as an answer (not a comment), then I can click the "accept" button :-)

Your Reply

By clicking “Post Your Reply”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.