Plot in the same app a graph and a table

This is my code:

I’ve alredy defined “df”

def plot_data(df, zscore= False, port = 1276):
    # Initialize the Dash app
    app = Dash(__name__)

    # Define the layout of the app
    app.layout = html.Div([
        dcc.Graph(id="graph"),
        html.P("Starting point of the interval:"),
        dcc.Slider(id="start-slider", min=1, max=len(df['comm_net'])-1, value=(len(df['comm_net'])-52), step=100),
        html.P("Maximum lag:"),
        dcc.Slider(id="lag-slider", min=1, max=len(df['comm_net']), value=(len(df['comm_net'])-52), step=100),
        dcc.Graph(id='grapi')
    ])

    @app.callback(
        Output("graph", "figure"), 
        Output("graph","table"),
        [Input("start-slider", "value"),
         Input("lag-slider", "value")]
        
    )
    def update_bar_chart(start, lag):
        # Slice the data based on the selected interval
        comm_data = df['comm_net'][start-1:start+lag-1]
        noncomm_data = df['noncomm_net'][start-1:start+lag-1]
        open_interest_data = df['open_interest_all'][start-1:start+lag-1]
        index_values = df.index[start-1:start+lag-1]

        # Create bar traces for comm_net and noncomm_net
        comm_trace = go.Bar(x=index_values, y=comm_data, name='Comm Net')
        noncomm_trace = go.Bar(x=index_values, y=noncomm_data, name='Noncomm Net')

        # Create a scatter trace for open_interest_all with a secondary y-axis
        open_interest_trace = go.Scatter(x=index_values, y=open_interest_data, mode='lines', name='Open Interest', yaxis='y2')

        # Create layout with secondary y-axis
        layout = go.Layout(
            title="Commitment of Traders",
            yaxis=dict(title='Comm & Noncomm Net'),
            yaxis2=dict(title='Open Interest', overlaying='y', side='right')
        )

        # Create a figure with both traces and layout
        fig = go.Figure(data=[comm_trace, noncomm_trace, open_interest_trace], layout=layout)
        

    
        fig2 = go.Figure(data=[go.Table(header=dict(values=['Non Commercial Net', 'ZScore Non Commercial','Difference from 1W ago','Commercial Net', 'ZScore Commercial','Difference from 1W ago','Open Interest']),
                         cells=dict(values=([round(df['noncomm_net'][-1],3)],[round(df['zscore_noncomm_net'][-1],3)], str(round(df['noncomm_net_diff'][-1],3)) + ' (' + str(round(df['noncomm_net_diffperc'][-1]*100,1)) + '%)', [round(df['comm_net'][-1],3)],
                                            [round(df['zscore_comm_net'][-1],3)], str(round(df['comm_net_diff'][-1],3)) + ' (' + str(round(df['comm_net_diffperc'][-1]*100,1)) + '%)', round(df['open_interest_all'][-1],3)))
                                      )])
        fig2.update_layout(height=150, margin=dict(t=20,b=10))
        fig2.add_annotation(x=0.5, y=-0.2,  # Adjust the y coordinate for the annotation
                   text="The Z-Score is computed as the distance, in terms of standard deviation, of the last available data from the mean of the last 52 weeks",
                   showarrow=False,
                   font=dict(size=10))
        fig2.show()
        return fig,fig2

        
    app.run_server(port=port)

I want that if zscore= True, it plots both the first graph(fig) and also the second (Fig2)(which is a table) in the same application.

Code of the app:

lista= ['COPPER', 'SILVER', 'GOLD', 'CRUDE OIL', 'U.S. DOLLAR INDEX']
import ipywidgets as widgets
from IPython.display import display, clear_output

# Create a dropdown widget for selecting the variable
variable_dropdown = widgets.Dropdown(
    options=lista,  
    value=lista[0],  
    description='Select Variable:'
)

# Create an output widget to display the results
output_widget = widgets.Output()

# Define a function to update the output based on the selected variable
def update_output(change):
    with output_widget:
        clear_output()
        selected_variable = variable_dropdown.value
        result = fetch_cftc_data(selected_variable)
        plot = plot_data(result,zscore=True, port=4)
        display(plot)

# Attach the function to the dropdown's observe event
variable_dropdown.observe(update_output, names='value')

# Arrange the widgets
container = widgets.VBox([
    variable_dropdown,
    output_widget
])

# Display the container
display(container)

Hey @GabriZG welcome to th community.

Unfortunately I don’t understand what are you trying to do. I understand the first code block- this is the function which creates the dash app.

Not sure what the second code block - what you refer to as app- is for, though.