Plotly marker line color based on dataframe column category
Question:
I have the following example df:
col1 col2 col3
0 1 10 C
1 2 15 A
2 3 20 A
3 4 25 A
4 5 30 B
5 6 35 B
6 7 40 B
7 8 45 B
8 9 50 B
9 10 55 B
And here is my simple code for the scatter plot below:
import plotly.express as px
import pandas aspd
df = pd.DataFrame({'col1':[1,2,3,4,5,6,7,8,9,10],
'col2':[10,15,20,25,30,35,40,45,50,55],
'col3':['C','A','A','A','B','B','B','B','B','B']})
fig = px.scatter(df, x='col1', y='col2', color='col3')
fig.update_traces(marker=dict(size=12))
fig.show()
The plot separates the colors of markers from col3
, however, I would like to make a plot with markers that are not filled with any color, but rather have the marker line colors from col3
.
Answers:
As you mentioned, I believe you are okay using plotly.graph_objects.
Here, I am using map
to assign a different color for each unique value in df.col3
(A, B, C). While plotting the scatter plot, you can set the marker fill color to transparent by using the rgba
(where a = alpha = transparency) to 0, meaning fully transparent
Then, using the line
(which is the border line to map to the color you want – in this case the col3.map(colors)
. You can also set the width of the edge line… Hope this is what you are looking for…
df = pd.DataFrame({'col1':[1,2,3,4,5,6,7,8,9,10],
'col2':[10,15,20,25,30,35,40,45,50,55],
'col3':['C','A','A','A','B','B','B','B','B','B']})
import plotly.graph_objects as go
colors={'A':'red', 'B':'blue', 'C':'green'}
fig = go.Figure()
fig.add_trace(go.Scatter(x=df.col1, y=df.col2,
marker=dict(size=12, color='rgba(255,255,255,0)',
line=dict(color=df['col3'].map(colors), width=3))))
Output Plot
OPTION 2
Here, I have modified the code so that the colors
dictionary now picks up all the unique values from the input dataframe-col3. As we don’t know the count of the unique values, I am using a colormap (plasma) to set the colors for the lines. You do need to add the colorscale
to this. You can of course choose a colormap to your liking. Hope this helps.
df = pd.DataFrame({'col1':[1,2,3,4,5,6,7,8,9,10],
'col2':[10,15,20,25,30,35,40,45,50,55],
'col3':['C','A','A','A','B','B','B','B','B','B']})
colors=dict(zip(df.col3.unique(), np.linspace(0,1,df.col3.nunique())))
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Scatter(x=df.col1, y=df.col2,
marker=dict(size=12, color='rgba(255,255,255,0)',
line=dict(color=df['col3'].map(colors), colorscale='plasma', width=3))))
Output Plot 2
If you are in fact happy with what your example code does with regards to color attribution based on 'col3':['C','A','A','A','B','B','B','B','B','B']
, then you can just add the following line to your snippet to produce circles with the same colors as the original markers, and no markers. In other words, holes in the middle:
fig.for_each_trace(lambda t: t.update(marker_line_color = t.marker.color, marker_line_width = 15,
marker_color = 'rgba(0,0,0,0)'))
Plot:
Complete code:
import pandas as pd
import plotly.express as px
import numpy as np
df = pd.DataFrame({'col1':[1,2,3,4,5,6,7,8,9,10],
'col2':[10,15,20,25,30,35,40,45,50,55],
'col3':['C','A','A','A','B','B','B','B','B','B']})
fig = px.scatter(df, x='col1', y='col2', color='col3')
fig.update_traces(marker=dict(size=8))
fig.show()
fig.for_each_trace(lambda t: t.update(marker_line_color = t.marker.color, marker_line_width = 15,
marker_color = 'rgba(0,0,0,0)'))
fig.show()
I have the following example df:
col1 col2 col3
0 1 10 C
1 2 15 A
2 3 20 A
3 4 25 A
4 5 30 B
5 6 35 B
6 7 40 B
7 8 45 B
8 9 50 B
9 10 55 B
And here is my simple code for the scatter plot below:
import plotly.express as px
import pandas aspd
df = pd.DataFrame({'col1':[1,2,3,4,5,6,7,8,9,10],
'col2':[10,15,20,25,30,35,40,45,50,55],
'col3':['C','A','A','A','B','B','B','B','B','B']})
fig = px.scatter(df, x='col1', y='col2', color='col3')
fig.update_traces(marker=dict(size=12))
fig.show()
The plot separates the colors of markers from col3
, however, I would like to make a plot with markers that are not filled with any color, but rather have the marker line colors from col3
.
As you mentioned, I believe you are okay using plotly.graph_objects.
Here, I am using map
to assign a different color for each unique value in df.col3
(A, B, C). While plotting the scatter plot, you can set the marker fill color to transparent by using the rgba
(where a = alpha = transparency) to 0, meaning fully transparent
Then, using the line
(which is the border line to map to the color you want – in this case the col3.map(colors)
. You can also set the width of the edge line… Hope this is what you are looking for…
df = pd.DataFrame({'col1':[1,2,3,4,5,6,7,8,9,10],
'col2':[10,15,20,25,30,35,40,45,50,55],
'col3':['C','A','A','A','B','B','B','B','B','B']})
import plotly.graph_objects as go
colors={'A':'red', 'B':'blue', 'C':'green'}
fig = go.Figure()
fig.add_trace(go.Scatter(x=df.col1, y=df.col2,
marker=dict(size=12, color='rgba(255,255,255,0)',
line=dict(color=df['col3'].map(colors), width=3))))
Output Plot
OPTION 2
Here, I have modified the code so that the colors
dictionary now picks up all the unique values from the input dataframe-col3. As we don’t know the count of the unique values, I am using a colormap (plasma) to set the colors for the lines. You do need to add the colorscale
to this. You can of course choose a colormap to your liking. Hope this helps.
df = pd.DataFrame({'col1':[1,2,3,4,5,6,7,8,9,10],
'col2':[10,15,20,25,30,35,40,45,50,55],
'col3':['C','A','A','A','B','B','B','B','B','B']})
colors=dict(zip(df.col3.unique(), np.linspace(0,1,df.col3.nunique())))
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Scatter(x=df.col1, y=df.col2,
marker=dict(size=12, color='rgba(255,255,255,0)',
line=dict(color=df['col3'].map(colors), colorscale='plasma', width=3))))
Output Plot 2
If you are in fact happy with what your example code does with regards to color attribution based on 'col3':['C','A','A','A','B','B','B','B','B','B']
, then you can just add the following line to your snippet to produce circles with the same colors as the original markers, and no markers. In other words, holes in the middle:
fig.for_each_trace(lambda t: t.update(marker_line_color = t.marker.color, marker_line_width = 15,
marker_color = 'rgba(0,0,0,0)'))
Plot:
Complete code:
import pandas as pd
import plotly.express as px
import numpy as np
df = pd.DataFrame({'col1':[1,2,3,4,5,6,7,8,9,10],
'col2':[10,15,20,25,30,35,40,45,50,55],
'col3':['C','A','A','A','B','B','B','B','B','B']})
fig = px.scatter(df, x='col1', y='col2', color='col3')
fig.update_traces(marker=dict(size=8))
fig.show()
fig.for_each_trace(lambda t: t.update(marker_line_color = t.marker.color, marker_line_width = 15,
marker_color = 'rgba(0,0,0,0)'))
fig.show()