0

I am trying to showcase a scatter plot as well as the data for the the plot side by side in jupyter. I wish to add a plotly button (dropdown) that will show the filtered data as well as the corresponding scatter plot. Is this possible WITHOUT USING ipywidgets, using plotly dropdowns?

I was able to build two separate plots for data and scatter plot with dropdowns but cannot combine them together. Following is the code I tried. Here the dropdown only interacts with the table, the scatter plot is not updating.

import plotly.express as px
import plotly.graph_objects as go
import numpy as np
import pandas as pd

df = px.data.iris()
species = sorted(set(df['species']))
#fig=go.Figure()
default_species = "setosa"
df_default = df[df['species']==default_species]

fig = make_subplots(
    rows=1, cols=2,
    shared_xaxes=True,
    horizontal_spacing=0.02,
    specs=[[{"type": "scatter"},{"type": "table"}]]
)
fig.add_trace(
    go.Scatter(
        x=df_default["sepal_length"],
        y=df_default["sepal_width"],
        mode="markers"
    ),
    row=1, col=1
)
fig.add_trace(
    go.Table(
        header=dict(
            values=["sepal<br>length","sepal<br>length","petal<br>length","petal<br>width","species","species<br>id"],
            font=dict(size=10),
            align="left"
        ),
        cells=dict(
            values=[df_default[k].tolist() for k in df_default.columns],
            align = "left")
    ),
    row=1, col=2
)

buttons = []
for s in species:
    s_data = df[df['species']==s]
    buttons.append(dict(
        method='restyle',
        label=s,
        visible=True,
        args=[ 
              {'values':[["sepal<br>length","sepal<br>length","petal<br>length","petal<br>width","species","species<br>id"]],
               'cells':[dict(values=[s_data[k].tolist() for k in s_data.columns],align = "left")]},
              {'y':[s_data["sepal_width"]],
               'x':[s_data['sepal_length']],
               'type':'scatter',
               'mode':'markers'}
             ]           
        
        ))
    
#fig.update_layout(width=1500, height=500)
# some adjustments to the updatemenus
updatemenu = []
your_menu = dict()
updatemenu.append(your_menu)

updatemenu[0]['buttons'] = buttons
updatemenu[0]['direction'] = 'down'
updatemenu[0]['showactive'] = True
updatemenu[0]['active'] = species.index(default_species)
updatemenu[0]['x'] = 0
updatemenu[0]['xanchor'] = 'left'
updatemenu[0]['y'] = 1.2
updatemenu[0]['yanchor'] = 'top'

# add dropdown menus to the figure
fig.update_layout(showlegend=False, 
                  updatemenus=updatemenu,
                  xaxis_title="Sepal_Length",
                  yaxis_title="Sepal_Width"
                 )
fig.show()

I do not want to use ipywidgets.

The code that worked for me: Editing hope it helps some one

## Create Combination of Scatter Plot and Plotly Tables with interactive Static HTML
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np
import pandas as pd

df = px.data.iris()
species_list = sorted(set(df['species']))

# --- function ---

def make_multi_plot(df1, item_list):

    fig = make_subplots(rows=1, 
                        cols=2,
                        #shared_xaxes=True,
                        #vertical_spacing=0.2,
                        specs = [[{}, {"type": "table"}]]
                            
                       )

    for item_id in item_list:
            #print('item_id:', item_id)
            
        trace1 = go.Scatter(
                x=df1.loc[df1.species.isin([item_id])].sepal_length, 
                y=df1.loc[df1.species.isin([item_id])].sepal_width,
                mode='markers',
                name = str(item_id)
        )
        fig.append_trace(trace1, 1, 1)
            
            
        trace2 = go.Table(
                columnorder = [1,2,3,4,5,6],
                columnwidth = [2,2,2,2,4,2],
                header=dict(
                    values = ["sepal<br>length","sepal<br>length","petal<br>length","petal<br>width","species","species<br>id"],
                    font = dict(size=10),
                    align = "left"
                ),
                cells = dict(
                    values = [df1[df1.species.isin([item_id])][k].tolist() for k in df1[df1.species.isin([item_id])].columns[:]],
                    align = "left"
                )
            )
        fig.append_trace(trace2,1,2)
        
    Ld = len(fig.data)
    #print(Ld)
    Lc = len(item_list)
        
    for k in range(2, Ld):
        fig.update_traces(visible=False, selector=k)
    
    def create_layout_button(k, item_id):
            #print(k, item_id)
            
        visibility = [False]*2*Lc
        for tr in [2*k, 2*k+1]:
                visibility[tr] = True
                
            #print(visibility)
                
        return dict(label = item_id,
                        method = 'restyle',
                        args = [{'visible': visibility,
                                 'title': item_id
                                 }])    
    
    #updatemenu[0]['x'] = 0
    #updatemenu[0]['xanchor'] = 'left'
    #updatemenu[0]['y'] = 1.2
    #updatemenu[0]['yanchor'] = 'top'
    fig.update_layout(
           updatemenus=[go.layout.Updatemenu(
               active=0,
               buttons=[create_layout_button(k, item_id) for k, item_id in enumerate(item_list)],
               x=0.5,
               y=1.3
           )],
           #title='Model Raporu',
           #template='plotly_dark',
           #height=800
           xaxis_title="Sepal_Length",
           yaxis_title="Sepal_Width"
        )
    
    fig.show()

# --- main ---
make_multi_plot(df1=df, item_list=species_list)
  • Need `from plotly.subplots import make_subplots` to make your code run. – Wayne Feb 28 '22 at 21:43
  • Yeah got it working. – Arindam Adak Mar 01 '22 at 07:43
  • That was mostly meant as a heads up for others trying to adapt what you posted. I should have worded it more to the general readers. Did you find a solution to your posted issue though? – Wayne Mar 01 '22 at 16:55
  • Yeah found it.. juat needed a little bit more understanding of it. – Arindam Adak Mar 02 '22 at 17:14
  • Since you worked out the solution, it would be nice if you can post an answer to your own question. Chances are if you struggled with something others may benefit. Plus, it allows you to have a nice resource to call upon months later when you are trying to remember how to do that again. – Wayne Mar 02 '22 at 17:26
  • 1
    Yeah good idea. I found this some where keeping it here would help out in future – Arindam Adak Mar 04 '22 at 15:57

0 Answers0