3D Scatter plot where each x,y pair has multiple z values

Hi all,
I want to create a 3D scatter plot where each x,y pair (‘Row’, ‘Column’) has multiple z values (‘Amounts’).
So for each amount there is a ‘Result’ value. With my code below there is only one dot for each x,y pair.
In other words, the ‘Amount’ axis represents different layers of the x,y plane containing the results for each x,y value.
So, ‘Row’ = 2 and ‘Column’ = 1 should have 5 dots with ‘Good’, ‘Medium’, ‘Good’, ‘Medium’, ‘Medium’

Is this even possible with plotly express, or is ‘graph objects’ the way to go?
Thanks!

import pandas as pd
import plotly.express as px

df = pd.DataFrame(
    {
        "Run": (
            1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4
        ),
        "Row": (
            1, 1, 2, 2, 1, 2, 2, 1, 1, 2, 2, 2, 1, 2, 1, 1
        ),
        "Column": (
            1, 2, 1, 2, 2, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 2
        ),
        "Type": (
            "Good", "Medium", "Good", "Bad", "Bad", "Medium", "Good", "Bad", "Good" , "Medium", "Medium", "Good", "Bad", "Medium", "Bad", "Good",
        ),
        "Square": (
            "1,1", "1,2", "2,1", "2,2", "1,2", "2,1", "2,1", "1,1", "1,2", "2,1", "2,2", "2,2", "1,1", "2,1", "1,1", "1,2",
        ),
        "Amounts" : (
            4, 4, 5, 3, 4, 5, 5, 4, 4, 5, 3, 3, 4, 5, 4, 4
        )
    }
)

fig = px.scatter_3d(df, 
        x="Column", 
        y="Row", 
        z="Amounts",
        color="Type",
)
                
fig.update_yaxes(autorange="reversed", tickvals=df["Row"].unique().tolist())
fig.update_xaxes(tickvals=df["Column"].unique().tolist())
fig.show()

Hi @Bakira , I think you will have to duplicate your x and y values as many times as amounts you have.

Hi @AIMPED,
thanks for your idea. However, I not sure if I fully understood the concept behind it. Because the dataframe df has the x,y value-pair as often as the “amount” columns shows.

So it turns out, that the logic of my dataframe was wrong. The column “Amounts” should not store the total amount of each square member but numbering each item from 0 to the length of that member group.

Adding following line did the trick:

df["Amounts"] = df.groupby("Square").cumcount()+1

Whole solution is as follows:

import pandas as pd
import plotly.express as px

df = pd.DataFrame(
    {
        "Run": (
            1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4
        ),
        "Row": (
            1, 1, 2, 2, 1, 2, 2, 1, 1, 2, 2, 2, 1, 2, 1, 1
        ),
        "Column": (
            1, 2, 1, 2, 2, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 2
        ),
        "Type": (
            "Good", "Medium", "Good", "Bad", "Bad", "Medium", "Good", "Bad", "Good" , "Medium", "Medium", "Good", "Bad", "Medium", "Bad", "Good",
        ),
        "Square": (
            "1,1", "1,2", "2,1", "2,2", "1,2", "2,1", "2,1", "1,1", "1,2", "2,1", "2,2", "2,2", "1,1", "2,1", "1,1", "1,2",
        ),
    }
)

df["Amounts"] = df.groupby("Square").cumcount()+1

fig = px.scatter_3d(df, 
        x="Column", 
        y="Row", 
        z="Amounts",
        color="Type",
)
                
fig.update_yaxes(autorange="reversed", tickvals=df["Row"].unique().tolist())
fig.update_xaxes(tickvals=df["Column"].unique().tolist())
fig.show()
1 Like