9

I have this interactive graph code using ipywidgets; but not sure how to arragne the each variable inside the interactive function in widgets. the default layout is vertical. But I want to arrange them in horizontal way.

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
plt.style.use('seaborn')
%config InlineBackend.figure_format = 'svg'
from ipywidgets import interactive,interact
#function to plot the different curves
def plot_function(u=1,v=2,w=3,x=4,y=5,z=6):
    time=np.arange(0,1,0.01)
    df=pd.DataFrame({"Y1":np.sin(time*u*2*np.pi),"y2":np.sin(time*v*2*np.pi),"y3":np.sin(time*w*2*np.pi),
                    "y4":np.sin(time*x*2*np.pi),"y5":np.sin(time*y*2*np.pi),"y6":np.sin(time*z*2*np.pi)})
    df.plot()
widget=interactive(plot_function,u=1,v=2,w=3,x=4,y=5,z=6)
widget

Output

Rafael
  • 7,605
  • 13
  • 31
  • 46
Bernad Peter
  • 504
  • 5
  • 12

3 Answers3

18

interactive is restricted to fairly simple widget layouts. Have a look at the Flexbox options if you want to customize them some more.

One simple get around is to use the interactive call to generate and link your widgets and functions, then restructure the widgets inside a HBox. Then add a layout that tells the box to wrap at line ends. I added a couple more imports and three lines at the end to achieve this.

1) controls - an HBox of your input widgets.

2) The Output widget generated by the interactive call.

3) A VBox that wraps the two together.

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
plt.style.use('seaborn')
%config InlineBackend.figure_format = 'svg'
#importing the necessary items from the Ipywidgets library 
from ipywidgets import interactive,interact, HBox, Layout,VBox
#function to plot the different curves
def plot_function(u=1,v=2,w=3,x=4,y=5,z=6):
    time=np.arange(0,1,0.01)
    df=pd.DataFrame({"Y1":np.sin(time*u*2*np.pi),"y2":np.sin(time*v*2*np.pi),"y3":np.sin(time*w*2*np.pi),
                    "y4":np.sin(time*x*2*np.pi),"y5":np.sin(time*y*2*np.pi),"y6":np.sin(time*z*2*np.pi)})
    df.plot()
widget=interactive(plot_function,u=1,v=2,w=3,x=4,y=5,z=6)
controls = HBox(widget.children[:-1], layout = Layout(flex_flow='row wrap'))
output = widget.children[-1]
display(VBox([controls, output]))

enter image description here

Bernad Peter
  • 504
  • 5
  • 12
ac24
  • 5,325
  • 1
  • 16
  • 31
  • You're welcome, if you're happy with the answer, consider accepting it by clicking the tick to the left. – ac24 Oct 31 '18 at 08:53
  • Is it possible to have plot_function be called on execution of this cell, rather than after the first manipulation of a widget? – Bananach May 12 '21 at 10:42
  • Don't think so, normally doing `display(widget)` will run the function once, but using the vBox approach means the function won't get run. – ac24 May 12 '21 at 11:19
  • You can do widget.update() to get the output displayed – Gilles Jul 05 '23 at 11:58
1

Hi this is the decorator which I am using instead of @interact:

def interact_delayed(_InteractFactory__interact_f=None, **kwargs):
    def patch(obj):
        if hasattr(obj.widget, 'layout'):
            obj.widget.layout = Layout(flex_flow='row wrap')
        for child in obj.widget.children:
            if hasattr(child, 'continuous_update'):
                child.continuous_update = False
        return obj
    if _InteractFactory__interact_f is None:
        def decorator(f):
            obj = interact(f, **kwargs)
            return patch(obj)
        return decorator
    else:
        obj = interact(_InteractFactory__interact_f, **kwargs)
        return patch(obj)

The patch function modifies default attributes of ipywidget object: applies the Layout suggested in the previous answer and also sets continuous_update to false which I found useful in my cases. The if-else branches takes care about decorator versus function use-case scenarios.

Alex Maystrenko
  • 1,091
  • 10
  • 11
0

There is no way to arrange widgets by adding a parameter in "interact" or interactive.