roudan
roudan

Reputation: 4200

Plotly: How to define marker color based on category string value for a 3d scatter plot?

I am using plotly.graph_object for 3D scatter plot. I'd like to define marker color based on category string value. The category values are A2, A3, A4. How to modify below code? Thanks

Here is what I did:


import plotly.graph_objects as go

x=df_merged_pc['PC1']
y=df_merged_pc['PC2']
z=df_merged_pc['PC3']

color=df_merged_pc['AREA']

fig=go.Figure(data=[go.Scatter3d(x=x,y=y,z=z,mode='markers',
                                 marker=dict(size=12,
                                             color=df_merged_pc['AREA'],
                                             colorscale ='Viridis'))])
fig.show()

The error I got is:

ValueError: 
    Invalid element(s) received for the 'color' property of scatter3d.marker
        Invalid elements include: ['A3', 'A3', 'A3', 'A3', 'A3', 'A3', 'A3', 'A2', 'A2', 'A2']

Upvotes: 5

Views: 10063

Answers (1)

vestland
vestland

Reputation: 61104

I might be wrong here, but it sounds to me like you're actually asking for a widely used built-in feature of plotly.express where you can assign a color to subgroups of labeled data. Take the dataset px.data.iris as an example with:

fig = px.scatter_3d(df, x='sepal_length', y='sepal_width', z='petal_width',
              color='species')

Here, the colors are assigned to different species of which you have three unique values ['setosa', 'versicolor', 'virginica']:

   sepal_length  sepal_width  petal_length  petal_width species  species_id
0           5.1          3.5           1.4          0.2  setosa           1
1           4.9          3.0           1.4          0.2  setosa           1
2           4.7          3.2           1.3          0.2  setosa           1
3           4.6          3.1           1.5          0.2  setosa           1
4           5.0          3.6           1.4          0.2  setosa           1

enter image description here

This example can be expanded upon by changing the color scheme like above, in which case your color scheme can be defined by a dictionary:

colors = {"flower": 'green', 'not a flower': 'rgba(50,50,50,0.6)'} 

Or you can specify a discrete color sequence with:

color_discrete_sequence = plotly.colors.sequential.Viridis

You can also add a new column like random.choice(['flower', 'not a flower']) to change the category you would like your colors associated with.

enter image description here

Plotly.graph_objects

If you would like to use go.Scatter3d instead I would build one trace per unique subgroup, and set up the colors using itertools.cycle like this:

colors = cycle(plotly.colors.sequential.Viridis)

fig = go.Figure()
for s in dfi.species.unique():
    df = dfi[dfi.species == s]
    fig.add_trace(go.Scatter3d(x=df['sepal_length'], y = df['sepal_width'], z = df['petal_width'],
                               mode = 'markers',
                               name = s,
                               marker_color = next(colors)))

Complete code for plotly express

import plotly.express as px
import random
df = px.data.iris()
colors = {"flower": 'green', 'not a flower': 'rgba(50,50,50,0.6)'}

df['plant'] = [random.choice(['flower', 'not a flower']) for obs in range(0, len(df))]
fig = px.scatter_3d(df, x='sepal_length', y='sepal_width', z='petal_width',
                color = 'plant',
                color_discrete_map=colors
                   )
fig.show()

Complete code for plotly graph objects

import plotly.graph_objects as go
import plotly
from itertools import cycle

dfi = px.data.iris()
colors = cycle(plotly.colors.sequential.Viridis)

fig = go.Figure()
for s in dfi.species.unique():
    df = dfi[dfi.species == s]
    fig.add_trace(go.Scatter3d(x=df['sepal_length'], y = df['sepal_width'], z = df['petal_width'],
                               mode = 'markers',
                               name = s,
                               marker_color = next(colors)))
fig.show()

Upvotes: 6

Related Questions