8-Bit Borges
8-Bit Borges

Reputation: 10033

Plotly - draw background shapes on radar plot

With the following function:

def plot_radar_analysis(df_team_matches, team=None, gameweek=None, kip=None):

  from math import pi
  import plotly.express as px
  from colors import full_team_colors

  gameweeks=range(1,gameweek+1)

  df_temp = df_team_matches.loc[(df_team_matches['ForTeam']==team[0])
                                &(df_team_matches['GameWeek'].isin(gameweeks))]

  indicator = df_temp[kip[0]]

  R = list(indicator.values)
  theta = [('Rodada ' + str(i)) for i in list(df_temp['GameWeek'].values)]

  color = full_team_colors[team[0]]

  df = pd.DataFrame(dict(
    r=R,
    theta=theta))

  fig = px.line_polar(df, r='r', theta='theta', line_close=True, title=f'{team[0]} - {kip[0]}')
  fig.update_polars(angularaxis_type="category") 
  fig.update_traces(fill='toself', line_color=color)
  fig.update_traces(mode="markers+lines")

  return fig

I plot this:

enter image description here


No I would like to add style to my radar plot, and add some low opacity shapes to my main figure in order to have the background look like this:

enter image description here

Please mind that football-related shapes should remain at background, and that the red area will go on top of those.


Can anyone point me in the right direction as to how I can draw these shapes and achieve a result that resembles the image above?

Upvotes: 2

Views: 1138

Answers (1)

Niko Fohr
Niko Fohr

Reputation: 33910

Maybe there's a better way to do this, but here is what I found.

Making polar grid transparent

  • Make the background color of the grid transparent by adding bgcolor="rgba(0, 0, 0, 0)" argument to your fig.update_polars call. (last zero is the important, other values don't matter)
    fig.update_polars(angularaxis_type="category",
                      bgcolor="rgba(223, 223, 223, 0)")

Adding image to background

  • Use pillow to create image object from a file on your hard disk
  • Add image with
from PIL import Image

fig.add_layout_image(
    dict(source=Image.open('bg_football.jpg'),
            xref="paper",
            yref="paper",
            x=0.5,
            y=0.5,
            sizex=1,
            sizey=1,
            sizing="contain",
            xanchor="center",
            yanchor="middle",
            opacity=0.5,
            layer="below"))

https://plotly.com/python/images/

  • The xref='paper' and yref='paper' make the image to be positioned with respect to paper. If xref='x' and yref='y', then the image is positioned with a cartesian coordinate axes. I did not find a possibility to position the image with respect to polar coordinates.
  • The x=0.5, y=0.5, xanchor='center', yanchor='middle' makes the image to be centered.
  • The sizing="contain" keeps the image size as-is. Other possible values are "contain" and "stretch".
  • source can be URL string or PIL.Image instance.

The resulting figure

results

Notes

  • In case you need to tweak the CSS to make the image be the same size as the plot in every situation & screen size etc.: The image will be placed in the DOM inside a <g class=layer-below>, which is different from the <g>-element with your polar plot (<g class=polarlayer>) and they have a common parent <svg class=main-svg>, which has parent <div class=svg-container>.

Additional resources

Upvotes: 2

Related Questions