If you want to output a graph with some parameters, the following methods can be considered as a method to check each time the parameters are changed.
The 1
method is a bit cumbersome to type. Even if it is on the IPython console, execute the function with Jupyter notebook
and rewrite the argument of the executed function ... Yes, it is troublesome.
How about the 2
method? It seems practical enough to output two or three graphs at once and compare them.
However, in a situation where there are 100 such parameters, it seems difficult to check with the human eye.
So, let's implement the 3
method.
It's easy to use ʻipywidgets to implement an interactive UI with
Jupyter notebook`.
The installation method is as follows.
pip install ipywidgets
jupyter nbextension enable --py widgetsnbextension
conda install -c conda-forge ipywidgets
ipywidgets.interact
You can create an interactive UI just by decorating ʻipywidgets.interact to the desired function. In the example below, the stock price is acquired and the moving average of the closing price for n days is output to the graph. If you give a numerical value to the argument of ʻinteract
, a slider will be displayed on the Jupyter notebook
, and adjusting this will change the parameter of the moving average.
n = (5, 30)
sets the minimum value to 5
and the maximum value to 30
.
You can also set n = 10
, which is the default value without any restrictions.
%matplotlib inline
from pandas_datareader.data import DataReader
from ipywidgets import interact
price = DataReader('^GSPC', 'yahoo', start='2016-01-01', end='2016-12-31')
@interact(n=(5, 30))
def plot_rolling_mean(n):
price['Adj Close'].plot()
price['Adj Close'].rolling(n).mean().plot()
In this way, it is possible to visually search for the appropriate value of the parameter in the UI.
As another example, let's change the graph type. If you give a tuple or list to the argument of ʻinteract`, a drop-down menu will be displayed. Let's use this to change the graph type in the UI.
@interact(kind=['line', 'area'])
def plot_line_or_band(kind):
price['Adj Close'].plot(kind=kind)
By preparing the UI and options in advance in this way, it is possible to intuitively encourage operations even for those who do not understand the program.
See also in Documentation, but for a list of UIs provided by ʻipywidgets, see ʻipywidgets.widgets.Widget.widget_types
. Is possible.
import ipywidgets as widgets
widgets.Widget.widget_types
There are only this ...
{'Jupyter.Accordion': ipywidgets.widgets.widget_selectioncontainer.Accordion,
'Jupyter.BoundedFloatText': ipywidgets.widgets.widget_float.BoundedFloatText,
'Jupyter.BoundedIntText': ipywidgets.widgets.widget_int.BoundedIntText,
'Jupyter.Box': ipywidgets.widgets.widget_box.Box,
'Jupyter.Button': ipywidgets.widgets.widget_button.Button,
'Jupyter.Checkbox': ipywidgets.widgets.widget_bool.Checkbox,
'Jupyter.ColorPicker': ipywidgets.widgets.widget_color.ColorPicker,
'Jupyter.Controller': ipywidgets.widgets.widget_controller.Controller,
'Jupyter.ControllerAxis': ipywidgets.widgets.widget_controller.Axis,
'Jupyter.ControllerButton': ipywidgets.widgets.widget_controller.Button,
'Jupyter.Dropdown': ipywidgets.widgets.widget_selection.Dropdown,
'Jupyter.FlexBox': ipywidgets.widgets.widget_box.FlexBox,
'Jupyter.FloatProgress': ipywidgets.widgets.widget_float.FloatProgress,
'Jupyter.FloatRangeSlider': ipywidgets.widgets.widget_float.FloatRangeSlider,
'Jupyter.FloatSlider': ipywidgets.widgets.widget_float.FloatSlider,
'Jupyter.FloatText': ipywidgets.widgets.widget_float.FloatText,
'Jupyter.HTML': ipywidgets.widgets.widget_string.HTML,
'Jupyter.Image': ipywidgets.widgets.widget_image.Image,
'Jupyter.IntProgress': ipywidgets.widgets.widget_int.IntProgress,
'Jupyter.IntRangeSlider': ipywidgets.widgets.widget_int.IntRangeSlider,
'Jupyter.IntSlider': ipywidgets.widgets.widget_int.IntSlider,
'Jupyter.IntText': ipywidgets.widgets.widget_int.IntText,
'Jupyter.Label': ipywidgets.widgets.widget_string.Label,
'Jupyter.PlaceProxy': ipywidgets.widgets.widget_box.PlaceProxy,
'Jupyter.Play': ipywidgets.widgets.widget_int.Play,
'Jupyter.Proxy': ipywidgets.widgets.widget_box.Proxy,
'Jupyter.RadioButtons': ipywidgets.widgets.widget_selection.RadioButtons,
'Jupyter.Select': ipywidgets.widgets.widget_selection.Select,
'Jupyter.SelectMultiple': ipywidgets.widgets.widget_selection.SelectMultiple,
'Jupyter.SelectionSlider': ipywidgets.widgets.widget_selection.SelectionSlider,
'Jupyter.Tab': ipywidgets.widgets.widget_selectioncontainer.Tab,
'Jupyter.Text': ipywidgets.widgets.widget_string.Text,
'Jupyter.Textarea': ipywidgets.widgets.widget_string.Textarea,
'Jupyter.ToggleButton': ipywidgets.widgets.widget_bool.ToggleButton,
'Jupyter.ToggleButtons': ipywidgets.widgets.widget_selection.ToggleButtons,
'Jupyter.Valid': ipywidgets.widgets.widget_bool.Valid,
'jupyter.DirectionalLink': ipywidgets.widgets.widget_link.DirectionalLink,
'jupyter.Link': ipywidgets.widgets.widget_link.Link}
As a matter of fact, I don't have the physical strength to explain all this, so I will use ʻipywidgets.widgets.Dropdown` as an example.
from IPython.display import display
d = widgets.Dropdown(options=['red', 'green', 'blue'], value='blue')
def on_value_change(change):
print(change['new'])
d.observe(on_value_change, names='value')
display(d)
The dropdown is displayed in ʻIPython.display.display and the event is handled in the ʻobserve
method.
The keyword argument names
is passed the properties to pass to the ʻon_value_changefunction. Normally use
'value'. When the dropdown value changes, ʻon_value_change
is called to print the value of the'value'
property.
Bokeh
has a convenient method called bokeh.io.push_notebook
, which allows you to handle graphs that have already been output and push changes to their contents.
Let's dynamically change the color of the graph object using the dropdown mentioned above.
from IPython.display import display
import ipywidgets as widgets
from bokeh.io import output_notebook, push_notebook
from bokeh.plotting import figure, show
d = widgets.Dropdown(options=['red', 'green', 'blue'], value='blue')
def on_value_change(change):
r.glyph.fill_color = change['new']
push_notebook(handle=t)
d.observe(on_value_change, names='value')
p = figure(width=250, height=250)
r = p.circle(1, 1, size=20, line_color=None)
output_notebook()
display(d)
t = show(p, notebook_handle=True)
The points here are the following two points.
notebook_handle = True
to the keyword arguments of thet = show (p, notebook_handle = True)
and show
methods to make the graph handleable.push_notebook (handle = t)
In this way, Bokeh
allows you to make changes to the graph object on Jupyter notebook
.
The above-mentioned matplotlib
ran the process of redrawing the entire graph, but Bokeh
allows you to change only the necessary parts, so you can lighten the process of dynamic graphs.
Compared to matplotlib
, Bokeh
has a function that is conscious of Jupyter notebook
from the beginning because it is a latecomer, and it seems that it can be said that it is a visualization tool that is compatible with Jupyter notebook
.
This was the introduction. This article is the 16th day of jupyter notebook Advent Calendar 2016. The 15th day was Yakiu no Hito, so I will continue to try Yakiu.
Let's make a simple pitching machine on the assumption that there is a pitcher that can dynamically change the position of the circle on the graph and throw it in the upper, middle and lower parts.
from random import randint
from bokeh.io import output_notebook, push_notebook
from bokeh.plotting import figure, show
from IPython.display import display
import ipywidgets as widgets
STRIKE_ZONE_HEIGHT = 750 #Strike zone height
STRIKE_ZONE_WIDTH = 432 #Strike zone width
STRIKE_ZONE_DIV = 3 #Divide into 3 and throw
zone_low = (0, int(STRIKE_ZONE_HEIGHT / STRIKE_ZONE_DIV)) #Low range
zone_mid = (zone_low[1], zone_low[1] * 2) #Middle range
zone_high = (zone_mid[1], STRIKE_ZONE_HEIGHT) #Higher range
#Decide the course
def get_cause(zone):
return randint(0, STRIKE_ZONE_WIDTH), randint(*zone)
#Throw to a fixed course
def pitch(zone):
x, y = get_cause(zone)
r.data_source.data['x'] = [x]
r.data_source.data['y'] = [y]
#This is the point! Push to the specified handle
push_notebook(handle=t)
#What happens when you click the button
def on_button_clicked(b):
cause_dict = {'High': zone_high, 'Mid': zone_mid, 'Low': zone_low}
pitch(cause_dict[b.description])
#Create a button object
h = widgets.Button(description="High")
m = widgets.Button(description="Mid")
l = widgets.Button(description="Low")
#Handling events when clicked
h.on_click(on_button_clicked)
m.on_click(on_button_clicked)
l.on_click(on_button_clicked)
output_notebook()
p = figure(
width=250,
height=250,
x_range=(0, STRIKE_ZONE_WIDTH),
y_range=(0, STRIKE_ZONE_HEIGHT))
#initial value
r = p.circle([STRIKE_ZONE_WIDTH / 2], [STRIKE_ZONE_HEIGHT / 2], size=20)
# notebook_handle=By adding True, you can operate it later.
t = show(p, notebook_handle=True)
display(h)
display(m)
display(l)
For buttons, you can pass control with an event handler called ʻon_click`. See the Widget Events documentation (https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Events.html) for more information. This time, the coordinates of the course were decided by random numbers, but if you insert the actual data and add the information of the ball type and ball speed, I think that you can implement the oleore one ball bulletin that is not inferior to the live baseball site. Previous person did the actual data collection, so if you are the one who is the one, please try it.
It's been a little longer, but here's a summary of what I wanted to tell you this time.
widgets
push_notebook
of Bokeh
makes it easier to create dynamic graphsʻIpywidgets and
Bokehare good tools for
Jupyter notebook`, but they have a low awareness.
I would be grateful if anyone could think of using this as an opportunity.
Recommended Posts