Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Plotly: How to assign background colors to different ranges in a radar or polar chart?

Tags:

python

plotly

I'm trying to change the background color of a radar chart in a way, that different value ranges get different colors, e.g. a radar chart with a range from 1-5, where 1-3 gets a red background color and 3-5 gets a green background color. There is a possibility to change the color, but only for the whole circle.

Do you have any ideas?

EDIT

This is the sample code that I've used with the only possibilities that I've found to add colors.

import plotly.graph_objects as go

categories = ['processing cost','mechanical properties','chemical stability',
              'thermal stability', 'device integration']

fig = go.Figure()

fig.add_trace(go.Scatterpolar(
      r=[1, 5, 2, 2, 3],
      theta=categories,
      fill='toself',
      name='Product A'
))
fig.add_trace(go.Scatterpolar(
      r=[4, 3, 2.5, 1, 2],
      theta=categories,
      fill='toself',
      name='Product B'
))

fig.update_layout(
  paper_bgcolor="red",
  polar=dict(
    radialaxis=dict(
      color="red",
      visible=True,
      range=[0, 5]
    )),
  showlegend=False
)

fig.show()
like image 777
Bene_91 Avatar asked Oct 20 '25 09:10

Bene_91


1 Answers

There's no direct way to specify different background colors for different parts of the plot. But I if I understand correctly what you're aiming for here, you can do so with the correct combination of some go.Barpolar() and go.Scatterpolar() traces:

enter image description here

Code:

# imports
import plotly.graph_objects as go
import numpy as np

# categories:
categories = ['processing cost','mechanical properties','chemical stability',
              'thermal stability', 'device integration']

# values:
rVars1=[1, 5, 2, 2, 3]
rVars2=[4, 3, 2.5, 1, 2]

# colors
values = [3,5]
colors = ['rgba(255, 0, 0, 0.8)', 'rgba(0, 255, 0, 0.8)']

# some calcultations to place all elements
slices=len(rVars1)
fields=[max(rVars1)]*slices
circle_split = [360/slices]*(slices)
theta= 0
thetas=[0]
for t in circle_split:
    theta=theta+t
    thetas.append(theta)
thetas

# plotly 
fig = go.Figure()

# "background"
for t in range(0, len(colors)):
    fig.add_trace(go.Barpolar(
        r=[values[t]],
        width=360,
        marker_color=[colors[t]],
        opacity=0.6,
        name = 'Range ' + str(t+1)
        #showlegend=False,
    ))
    t=t+1

# trace 1
fig.add_trace(go.Scatterpolar(
       text = categories,
        r = rVars1,
        mode = 'lines+text+markers',
        fill='toself',
        fillcolor='rgba(0, 0, 255, 0.4)',
        textposition='bottom center',
        marker = dict(color = 'blue'),
        name = 'Product A'))

# adjust layout
fig.update_layout(
    template=None,
    polar = dict(radialaxis = dict(gridwidth=0.5,
                               range=[0, max(fields)], 
                              showticklabels=True, ticks='', gridcolor = "grey"),
                 angularaxis = dict(showticklabels=False, ticks='',
                               rotation=45,
                               direction = "clockwise",
                               gridcolor = "white")))

fig.update_yaxes(showline=True, linewidth=2, linecolor='white')
fig.show()

Edit: Multiple traces

Your sample code covers multiple traces. And that would quickly turn into a fine mess with my initial approach. Below is a snippet that covers multiple traces. To make this look good, I've put the category names at the edge of the circle in it's own trace with various text positions to make the names fall on the outside of the circle. Then I'm adding a single trace for each Product A and B. I hope this will be useful.

Plot 2:

enter image description here

Code 2:

# imports
import plotly.graph_objects as go
import numpy as np
import pandas as pd

# categories:
categories = ['processing cost','mechanical properties','chemical stability',
              'thermal stability', 'device integration']

# values:
rVars1=[1, 5, 2, 2, 3]
rVars2=[4, 3, 2.5, 1, 2]

rAllMax = max(rVars1+rVars2)

# colors
values = [3,5]
colors = ['rgba(255, 0, 0, 0.9)', 'rgba(0, 255, 0, 0.9)', ]

# some calcultations to place all elements
slices=len(rVars1)
fields=[max(rVars1)]*slices
circle_split = [360/slices]*(slices)
theta= 0
thetas=[0]
for t in circle_split:
    theta=theta+t
    thetas.append(theta)
thetas

# set up label positions
df_theta=pd.DataFrame({'theta':thetas, 'positions':['middle right', 'middle right',
                                                    'bottom center', 'middle left',
                                                    'middle left', 'middle left']})


# plotly 
fig = go.Figure()

# "background"
for t in range(0, len(colors)):
    fig.add_trace(go.Barpolar(
        r=[values[t]],
        width=360,
        marker_color=[colors[t]],
        opacity=0.6,
        name = 'Range ' + str(t+1)
        #showlegend=False,
    ))
    t=t+1

for r, cat in enumerate(categories):
    #print(r, cat)
    fig.add_trace(go.Scatterpolar(
            text = cat,
            r = [rAllMax],
            theta = [thetas[r]],
            mode = 'lines+text+markers',
            fill='toself',
            fillcolor='rgba(255, 255, 255, 0.4)',
            line = dict(color='black'),
            #textposition='bottom center',
            textposition=df_theta[df_theta['theta']==thetas[r]]['positions'].values[0],
            marker = dict(line_color='white', color = 'black'),
            marker_symbol ='circle',
            name = cat,
            showlegend = False))



# trace 1
fig.add_trace(go.Scatterpolar(
        #text = categories,
        r = rVars1,
        mode = 'lines+text+markers',
        fill='toself',
        fillcolor='rgba(0, 0, 255, 0.4)',
        textposition='bottom center',
        marker = dict(color = 'blue'),
        marker_symbol ='square',
        name = 'Product A'))

# trace 2
fig.add_trace(go.Scatterpolar(
        #text = categories,
        r = rVars2,
        mode = 'lines+text+markers',
        fill='toself',
        fillcolor='rgba(0, 255, 0, 0.4)',
        textposition='bottom center',
        marker = dict(color = 'Green'),
        name = 'Product B'))


# adjust layout
fig.update_layout(
    template=None,
    polar = dict(radialaxis = dict(gridwidth=0.5,
                               range=[0, max(fields)], 
                              showticklabels=True, ticks='', gridcolor = "grey"),
                 angularaxis = dict(showticklabels=False, ticks='',
                               rotation=45,
                               direction = "clockwise",
                               gridcolor = "white")))

fig.update_yaxes(showline=True, linewidth=2, linecolor='white')
fig.show()
like image 200
vestland Avatar answered Oct 22 '25 23:10

vestland



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!