Search code examples
pythondataframeplotlybar-chartpolar-coordinates

How to add an image to a bar polar chart?


import plotly.express as px
img = Image.open('/content/drive/My Drive/Colab Notebooks/clock.png')
df = df.iloc[0:24,:]

fig = px.bar_polar(df, r=df['datetime'],  theta =  
[0,15.0,30.0,45.0,60.0,75.0,90.0,105.0,120.0,135.0, 
150.0,165.0,180.0,195.0,210.0,225.0,240.0,255.0,270.0,285.0,300.0,315.0,330.0, 345],
               color=df['power'],direction='clockwise',range_r=[0,0],range_theta=[0, 360], 
               color_discrete_sequence= px.colors.sequential.Plasma_r)
 # Add images
fig.add_layout_image(
dict(
    source=img,
    xref="paper",
    yref="paper",
    x=0.18,
    y=1.27,
    sizex=1.6,
    sizey=1.6,
    sizing="contain",
    layer="below"
   ))

   fig.show()

df= {'datetime': {0: '10/11/2012 00:00', 1: '10/11/2012 00:30', 2: '10/11/2012 01:00', 3: '10/11/2012 01:30', 4: '10/11/2012 02:00'}, 'power': {0: 2486, 1: 227, 2: 229, 3: 137, 4: 192}}

img=enter image description here

Hi, I want to add this clock image to this bar polar chart. Both bar charts can be placed around to clock and the clock can be placed inside the bar charts. Can anybody help with this, please? Also, I want to remove degrees, grids and axes from the chart. Also, I have a problem with missing data, somehow the first row is missing in the bar chart and why I did not understand it. If anyone can help with this, I d appreciate it.


Solution

  • If a time series is used as an axis in a polar bar chart, the time series must be converted to an angle. I have extended your sample data so that you have data for all 12 hours. I couldn't find a suitable image equivalent to a clock dial, so I used mathjax for the ticks and set the text size to Huge, with only the required time display. if you set showticklabels=False, the dial I set will not be displayed. Now all I need to do is set your image as the background and I think it will happen!

    import pandas as pd
    import numpy as np
    import plotly.express as px
    #img = Image.open('/content/drive/My Drive/Colab Notebooks/clock.png')
    
    data = {'datetime': {0: '10/11/2012 00:00', 
                         1: '10/11/2012 00:30',
                         2: '10/11/2012 01:00',
                         3: '10/11/2012 01:30',
                         4: '10/11/2012 02:00',
                         5: '10/11/2012 02:30',
                         6: '10/11/2012 03:00',
                         7: '10/11/2012 03:30',
                         8: '10/11/2012 04:00',
                         9: '10/11/2012 04:30',
                         10: '10/11/2012 05:00',
                         11: '10/11/2012 05:30',
                         12: '10/11/2012 06:00',
                         13: '10/11/2012 06:30',
                         14: '10/11/2012 07:00',
                         15: '10/11/2012 07:30',
                         16: '10/11/2012 08:00',
                         17: '10/11/2012 08:30',
                         18: '10/11/2012 09:00',
                         19: '10/11/2012 09:30',
                         20: '10/11/2012 10:00',
                         21: '10/11/2012 10:30',
                         22: '10/11/2012 11:00',
                         23: '10/11/2012 11:30'}, 
            'power': dict(zip(np.arange(24), np.random.randint(50,2500, 24)))}
    
    df = pd.DataFrame.from_dict(data)
    df['datetime'] = pd.to_datetime(df['datetime'])
    df['theta'] = df['datetime'].dt.hour * 30 + df['datetime'].dt.minute * 0.5
    #print(df)
    ticktexts = [f'$\Huge\mathsf{i}$' if i % 3 == 0 else '' for i in np.arange(12)]
    theta = np.arange(0, 360, 15)
    
    fig = px.bar_polar(df, r=df['power'],
                       theta=df['theta'],
                       color=df['power'],
                       direction='clockwise',
                       range_r=[0,2500],
                       range_theta=[0, 360],
                       color_discrete_sequence=px.colors.sequential.Plasma_r)
    
    fig.update_layout(polar=dict(angularaxis=dict(tickvals=np.arange(0,360,30),
                                                  #ticktext=[str(x) for x in np.arange(12)],
                                                  ticktext=ticktexts,
                                                  showticklabels=True,
                                                  showline=False,
                                                  showgrid=False,
                                                  linewidth=3,
                                                  ticks='inside'
                                                 ),
                                 radialaxis = dict(showticklabels=False,
                                                   ticks='',
                                                   showline=False,
                                                   showgrid=False,
                                                   gridcolor='white'
                                                  )),
                      template=None,
                     )
    fig
    

    enter image description here