✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🧬 Learn how to build RNA-Seq data apps with Python & Dash. Register for the May 20 Webinar!

How to get 2 extra x and y axes text to display

Hi All, I am trying to add 2 new axes to my plotly heatmap, "i_value’ to the xaxes and “l_freq” to the yaxes. I have ad a search around the web and looked at this example but I can’t work it out. Figure Factory Subplots | Python | Plotly

Can someone show me where I’m going wrong? I thought it would just be an update to layout but that doesn’t seem to work.

I have the basic heatmap working fine and outputting what I want initially.

Now I want to up the ante with a second plot but I need to be able to define the axes first.
Here is my code for preping and displaying the heatmap. its a bit lengthy butyh hopefully the comments are help[full


def do_heatmaps():
    
    # Define our groups of business units
    # all_teams - All business Units
    # first_line - Firstline teams
    # second_line - All secondline teams (Control Functions)
    # all_it - All teams demmed to be IT

    all_it = ['BCM', 'Business Inteligence' ,'IT Development' ,'IT Production' ,'Stockbroking Web Development', 'Information Security']
    first_line = ['Client Services', 'Client Services APAC', 'Institutional Sales & Partners', 'Stockbroking Partners', 'Sales Trading', 'Trading incl. Pricing and Risk Dev', 'Marketing', 'Business Operations', 'Stockbroking Dealing & Business Operations', 'Market Data', 'Stockbroking Operations', 'Stockbroking Operations - APAC', 'Client Money', 'Stockbroking Client Money', 'Facilities', 'Business Change', 'GmbH', 'HR', 'Company Secretariat', 'Company Secretariat - APAC', 'Tax']
    second_line = ['Finance', 'Legal', 'Data Privacy', 'Operational Risk', 'Financial Risk', 'Liquidity Risk', 'Compliance', 'Financial Crime']
    all_teams = [all_it, first_line, second_line]
    
    # Create our temp dataframe df and pull in the data we are interested in.
    # We also use this oppertunity to remove blank entries
    temp_df = raca_df[['risk_id', 'gross_impact','gross_likelihood', 'business_unit', 'net_impact', 'net_likelihood']].dropna()
        
    # Get user to enter what functions they want reporting on. All, II, First Line, or Second line   
    def get_departments():
       
        # Our prompt
        prompt = 'Enter either All, IT, First, or Second to create matrix for these to create the relevant heatmap: '
        
        while True:
            try:
                dept = input(prompt)
            except ValueError:
                print("Sorry, Only enter All, IT, First, or Second.")
                continue

            while dept not in ['All', 'IT', 'First', 'Second']:
                print('Sorry, Invalid Input. Please try again')
                dept = input('Enter either All, IT, First, or Second to create '
                             'matrix for these to create the relevant heatmap: ')
                continue
            else:
                break
        
        # Return user choice to our do_heatmaps() function
        return dept

    # Call get_departments() function and assign output to variable dept
    dept = get_departments()
    
    
    # Get our data ready for the heatmap
    def heatmap_prep(data):
        ## Likelihood Assesment Weightings
        ## We have taken the midpoint in each of the ranges
        
        # Highly Possible - Likely to crystalise more than once a year > 80%
        la_hp = float(0.90)

        # Possible - Likely to crystalise between once every two and a half years and once a year 40% to 80%
        la_p = float(0.60)
        
        # Unlikely - Likely to crystalise between once every five years and up to once every two and a half years 20% to 40%
        la_u = float(0.30)
        
        # Remote - Likely to crystalise between once every ten years and up to once every five years 10% to 20%
        la_r = float(0.10)
        
        # Very Remote - Likely to crystalise less than once every ten years < 10%
        la_vr = float(0.05)
        
        ## Frequency Assesment weightings
        ## We have taken the midpoint in each of the ranges
        
        # Highly Possible - 50% chance of happening in the next 12 months or occurs at least once every 2 years 
        fa_hp = float(0.50)
        
        # Possible - 20% – 50% chance of happening in the next 12 months or occurs once in every 2 to 5 years 
        fa_p = float(0.35)
        
        # Unlikely - 10% - 20% chance of happening in the next 12 months or occurs once in every 5 to 10 years 
        fa_u = float(0.15)
        
        # Remote - ≤10% chance of happening in the next 12 months or occurs less than once in every 10 to 20 years 
        fa_r = float(0.05)
        
        # Very Remote - ≤5% chance of happening in the next 12 months or occurs less than once in every 20 to 100 years
        fa_vr = float(0.025)
        
        # Extremly Remote - ≤1% chance of happening in the next 12 months or occurs no more than once in every 100 to 200
        # years or less 
        fa_er = float(0.005)
        
                
        # Set our heatmap dataframe dependant on value of dept
        if dept == 'IT':
            hm_df = temp_df[temp_df["business_unit"].isin([val for val in all_it])]
        elif dept == 'First':
            hm_df = temp_df[temp_df["business_unit"].isin([val for val in first_line])]
        elif dept == 'Second':
            hm_df = temp_df[temp_df["business_unit"].isin([val for val in second_line])]
        elif dept == 'All':
            hm_df = temp_df[temp_df["business_unit"].isin([val for sublist in all_teams for val in sublist])]
        else:
            print('Now how the fudge did we get here!!!!!!!')


        # loop through our columns and set the type accordingly. 
        # Here we set it to int to prevent us getting the following error
        # "IndexError: arrays used as indices must be of integer (or boolean) type"
        for item in ['gross_impact','gross_likelihood','net_impact', 'net_likelihood']:
            hm_df[item] = hm_df[item].astype('int')

        # get our counts of the gross number of impact,likelihood pair
        grosscount = hm_df.groupby(['gross_impact','gross_likelihood']).apply(len).reset_index().values

        # # get our counts of the number of impact,likelihood pair
        netcount = hm_df.groupby(['net_impact','net_likelihood']).apply(len).reset_index().values

        # # Set up a blank 5 x 5 array and fill with zeros - Gross
        heatmap_gr = np.zeros((np.max(5), np.max(5)),dtype=int)

        # # Set up a blank 5 x 5 array and fill with zeros - Net
        heatmap_nr = np.zeros((np.max(5), np.max(5)),dtype=int)
        
        # # Set up a blank 5 x 5 array and fill with zeros - Weighted Inherent
        weighted_gr = np.zeros((np.max(5), np.max(5)), dtype=float)
        
        # # Set up a blank 5 x 5 array and fill with zeros - Weighted Residual
        weighted_nr = np.zeros((np.max(5), np.max(5)), dtype=float)
        

        # # Map the counts to our matrix
        # # the -1 makes python count from 1 not 0. 
        heatmap_gr[grosscount[:,1]-1, grosscount[:,0]-1] = grosscount[:,2]

        heatmap_nr[netcount[:,1]-1, netcount[:,0]-1] = netcount[:,2]
        
        # Create copies of our gross and net risk arrays so we can apply a likelihood weighting.

        # Setup our weighted risk arrays for Inherent (Gross) and Residual (net) risk
        #Inherent
        weighted_gr[0] = heatmap_gr[0] * la_vr
        weighted_gr[1] = heatmap_gr[1] * la_r
        weighted_gr[2] = heatmap_gr[2] * la_u
        weighted_gr[3] = heatmap_gr[3] * la_p
        weighted_gr[4] = heatmap_gr[4] * la_hp
        
        # Set to 2 decimal places
        np.round(weighted_gr,decimals = 2)
   
        
        #Residual
        weighted_nr[0] = heatmap_nr[0] * la_vr
        weighted_nr[1] = heatmap_nr[1] * la_r
        weighted_nr[2] = heatmap_nr[2] * la_u
        weighted_nr[3] = heatmap_nr[3] * la_p
        weighted_nr[4] = heatmap_nr[4] * la_hp
        
        # Set to 2 decimal places 
        np.round(weighted_nr,decimals = 2)
        
        # X axes labels
        impact=['Minor', 'Important', 'Significant', 'Major', 'Critical']
        i_value = ['> £5m',
                   '< £5m',
                   '< £2m',
                   '< £250k',
                   '< 50k'
                  ]
        
        # Y axes labels
        likelihood=['Very Remote', 'Remote', 'Unlikely', 'Possible', 'Highly Possible']
        l_freq = ['50% chance of happening in the next 12 months or occurs at least once every 2 years', 
                  '20% – 50% chance of happening in the next 12 months or occurs once in every 2 to 5 years', 
                  '10% - 20% chance of happening in the next 12 months or occurs once in every 5 to 10 years',
                  '≤10% chance of happening in the next 12 months or occurs less than once in every 10 to 20 years',
                  '≤5% chance of happening in the next 12 months or occurs less than once in every 20 to 100 years'
                 ]
        

        # Only show rounded value
        gr_text = np.round(heatmap_gr, decimals=2)
        nr_text = np.round(heatmap_nr, decimals=2)
        wgr_text = np.round(weighted_gr, decimals=2)
        wnr_text = np.round(weighted_nr, decimals=2)

        # Setup our hovertext for gross risk
        # This piece of code remaps x, y, and z to whatever we specify inour hovertext_gr line in the second for loop
        hovertext_gr = list()
        for yi, yy in enumerate(likelihood):
            hovertext_gr.append(list())
            for xi, xx in enumerate(impact):
                hovertext_gr[-1].append('Impact: {}<br />Likelihood: {}<br />Number of Risks: {}'.format(xx,yy,heatmap_gr[yi][xi]))
                
        # Setup our hovertext for net risk
        # This piece of code remaps x, y, and z to whatever we specify inour hovertext_nr line in the second for loop
        hovertext_nr = list()
        for yj, yz in enumerate(likelihood):
            hovertext_nr.append(list())
            for xj, xz in enumerate(impact):
                hovertext_nr[-1].append('Impact: {}<br />Likelihood: {}<br />Number of Risks: {}'.format(xz,yz,heatmap_nr[yj][xj]))
                
            return heatmap_gr, heatmap_nr, impact, likelihood, gr_text, nr_text, wgr_text, wnr_text, hovertext_gr, hovertext_nr, weighted_gr, weighted_nr, i_value, l_freq
  
    # Unpack our return values from heatmap_prep function
    heatmap_gr, heatmap_nr, impact, likelihood, gr_text, nr_text, wgr_text, wnr_text, hovertext_gr, hovertext_nr, weighted_gr, weighted_nr, i_value, l_freq = heatmap_prep(dept)
    
    
    def display_heatmap(heatmap_gr, heatmap_nr, impact, likelihood, gr_text, nr_text, wgr_text, wnr_text, hovertext_gr, hovertext_nr, weighted_gr, weighted_nr, i_value, l_freq):
            
        fig_gr = ff.create_annotated_heatmap(heatmap_gr,
                                             x=impact,
                                             y=likelihood,
                                             colorscale='Blues',
                                             hoverinfo ='text',
                                             text = hovertext_gr
                                             )
        
        fig_nr = ff.create_annotated_heatmap(heatmap_nr,
                                             x=impact,
                                             y=likelihood,
                                             colorscale='Blues',
                                             hoverinfo ='text',
                                             text = hovertext_nr
                                            )
        
        weight_gr = ff.create_annotated_heatmap(weighted_gr,
                                                  x=impact,
                                                  y=likelihood,
                                                  colorscale='Reds',
                                                  hoverinfo ='text',
                                                  text = hovertext_gr
                                                 )
        
        weight_nr = ff.create_annotated_heatmap(weighted_nr,
                                                  x=impact,
                                                  y=likelihood,
                                                  colorscale='Reds',
                                                  hoverinfo ='text',
                                                  text = hovertext_nr
                                                 )
                
        # Setup the Heatmap layout for our Heatmaps
        if dept == 'IT':
            fig_gr.layout.update({'title': "Gross Risk Distribution - All IT (Count)"}, title_x=0.5)
            fig_nr.layout.update({'title': "Net Risk Distribution - All IT (Count)"}, title_x=0.5)
            weight_gr.layout.update({'title': "Inherent Risk - All IT (Weighted)"}, title_x=0.5)
            weight_nr.layout.update({'title': "Residual Risk - All IT (Weighted)"}, title_x=0.5)

#             # initialize xaxis2 and yaxis2
#             fig_gr['layout']['xaxis2'] = {}
#             fig_gr['layout']['yaxis2'] = {}

#             # Edit layout for subplots
#             fig_gr.layout.yaxis.update({'domain': [0, .5]})
#             fig_gr.layout.yaxis2.update({'domain': [.6, 1]})

#             # The graph's yaxis2 MUST BE anchored to the graph's xaxis2 and vice versa
#             fig_gr.layout.yaxis2.update({'anchor': 'x2'})
#             fig_gr.layout.xaxis2.update({'anchor': 'y2'})
#             fig_gr.layout.yaxis2.update({'title': l_freq[0]}, title=0.5)
            


        elif dept == 'First':
            fig_gr.layout.update({'title': "Gross Risk Distribution - First Line Functions (Count)"}, title_x=0.5)
            fig_nr.layout.update({'title': "Net Risk Distribution - First Line Functions (Count)"}, title_x=0.5)
            weight_gr.layout.update({'title': "Inherent Risk - First Line (Weighted)"}, title_x=0.5)
            weight_nr.layout.update({'title': "Residual Risk - First Line (Weighted)"}, title_x=0.5)
        elif dept == 'Second':
            fig_gr.layout.update({'title': "Gross Risk Distribution - Second Line Functions (Count)"}, title_x=0.5)
            fig_nr.layout.update({'title': "Net Risk Distribution - Second Line Functions (Count)"}, title_x=0.5)
            weight_gr.layout.update({'title': "Inherent Risk - Second Line (Weighted)"}, title_x=0.5)
            weight_nr.layout.update({'title': "Residual Risk - Second Line (Weighted)"}, title_x=0.5)
        elif dept == 'All':
            fig_gr.layout.update({'title': "Gross Risk Distribution - All Business Functions (Count)"}, title_x=0.5)
            fig_nr.layout.update({'title': "Net Risk Distribution - All Business Functions (Count)"}, title_x=0.5)
            weight_gr.layout.update({'title': "Inherent Risk - All Business Functions  (Weighted)"}, title_x=0.5)
            weight_nr.layout.update({'title': "Residual Risk - All Business Functions  (Weighted)"}, title_x=0.5)
            
        else:
            print('Now how the fudge did we get here!!!!!!!')


        fig_gr.show()
        weight_gr.show()
        fig_nr.show()
        weight_nr.show()
        
    display_heatmap(heatmap_gr, heatmap_nr, impact, likelihood,
                    gr_text, nr_text, wgr_text, wnr_text,
                    hovertext_gr, hovertext_nr, weighted_gr, weighted_nr,
                    i_value, l_freq
                   )