Interactive data visualization

Interactive data visualization#

Ipython widgets are useful in adding interactivity in Jupyter notebook and the rendered HTML pages. These widgets are particularly helpful in creating interactive graphs and to enable customized rendering of dataframes.

import matplotlib.pyplot as plt
import numpy as np
from IPython.display import Markdown, display, HTML
from ipywidgets import widgets, interact
def plot1(Numbers):
    x = range(1,Numbers+1)
    y = [a**2 for a in x]
    plt.bar(x,y)
    plt.xlabel("Number")
    plt.ylabel("Square")
interact(plot1, Numbers=widgets.IntSlider(min=5, max=20, step=1, value=10));

Toogle widget

def plot2(calc):
    with out:
        x = range(1,5+1)
        y = [a**2 for a in x]
        z = [a**3 for a in x]
        if(calc=="Squares"):
            plt.bar(x,y, width=0.4, label="Squares")
            plt.xlabel("Number")
            plt.ylabel("Square")
        if(calc=="Cubes"):
            plt.bar(x,z, width=0.4, label="Cubes")
            plt.xlabel("Number")
            plt.ylabel("Cube")
        if(calc=="both"):
            X_axis = np.arange(len(x))
            plt.bar(X_axis-0.1,y, width=0.2, label="Squares")
            plt.bar(X_axis+0.1,z, width=0.2, label="Cubes")
            plt.xlabel("Number")
            plt.ylabel("Square/Cube")
            plt.legend()
toggle = widgets.ToggleButtons(
    options=['Squares', 'Cubes','both'],
    description='Y-axis:',
    disabled=False,
    button_style='', 
    tooltips=['Calculate squares', 'Calculate cubes', 'Calculate both'],
)
out = widgets.Output()
@interact
def clicked(a=toggle):
    plot2(a)

Converting notebooks to html#

The interactive visualizations within the notebooks can be converted to static webpages in the html format. The nbconvert package facilitates converting Jupyter notebooks to html. It can be installed via pip install nbconvert. Once installed, the following command can be used to convert a notebook test.ipynb to the html format.

jupyter nbconvert --to html test.ipynb

The resulting html file can be uploaded on any of the web hosting services such as Google Sites.

Bokeh library#

Installation - pip install bokeh

import pandas as pd
from bokeh.plotting import figure, show
## for showing graphs inside Jupyter notebook 
from bokeh.resources import INLINE
import bokeh.io
bokeh.io.output_notebook(INLINE)
BokehJS 3.4.1 successfully loaded.
x = range(1,6)
y = [a**2 for a in x]
z = [b**3 for b in x]
p = figure(title="Line plot", x_axis_label='Number', y_axis_label='Value',\
          width=500, height=250)
p.line(x, y, legend_label="Square", color="teal", line_width=2)
p.line(x, z, legend_label="Cube", color="orange", line_width=2) 
show(p)
---------------------------------------------------------------------------
SerializationError                        Traceback (most recent call last)
Cell In[8], line 8
      6 p.line(x, y, legend_label="Square", color="teal", line_width=2)
      7 p.line(x, z, legend_label="Cube", color="orange", line_width=2) 
----> 8 show(p)

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\io\showing.py:149, in show(obj, browser, new, notebook_handle, notebook_url, **kwargs)
    146 state = curstate()
    148 if isinstance(obj, UIElement):
--> 149     return _show_with_state(obj, state, browser, new, notebook_handle=notebook_handle)
    151 def is_application(obj: Any) -> TypeGuard[Application]:
    152     return getattr(obj, '_is_a_bokeh_application_class', False)

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\io\showing.py:196, in _show_with_state(obj, state, browser, new, notebook_handle)
    194 if state.notebook:
    195     assert state.notebook_type is not None
--> 196     comms_handle = run_notebook_hook(state.notebook_type, 'doc', obj, state, notebook_handle)
    197     shown = True
    199 if state.file or not shown:

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\io\notebook.py:372, in run_notebook_hook(notebook_type, action, *args, **kwargs)
    370 if _HOOKS[notebook_type][action] is None:
    371     raise RuntimeError(f"notebook hook for {notebook_type!r} did not install {action!r} action")
--> 372 return _HOOKS[notebook_type][action](*args, **kwargs)

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\io\notebook.py:608, in show_doc(obj, state, notebook_handle)
    606 from ..embed.notebook import notebook_content
    607 comms_target = make_id() if notebook_handle else None
--> 608 (script, div, cell_doc) = notebook_content(obj, comms_target)
    610 publish_display_data({HTML_MIME_TYPE: div})
    611 publish_display_data({JS_MIME_TYPE: script, EXEC_MIME_TYPE: ""}, metadata={EXEC_MIME_TYPE: {"id": obj.id}})

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\embed\notebook.py:90, in notebook_content(model, notebook_comms_target, theme)
     87 # Comms handling relies on the fact that the new_doc returned here
     88 # has models with the same IDs as they were started with
     89 with OutputDocumentFor([model], apply_theme=theme, always_new=True) as new_doc:
---> 90     (docs_json, [render_item]) = standalone_docs_json_and_render_items([model])
     92 div = div_for_render_item(render_item)
     94 render_item = render_item.to_json()

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\embed\util.py:333, in standalone_docs_json_and_render_items(models, suppress_callback_warning)
    331 docs_json: dict[ID, DocJson] = {}
    332 for doc, (docid, _) in docs.items():
--> 333     docs_json[docid] = doc.to_json(deferred=False)
    335 render_items: list[RenderItem] = []
    336 for _, (docid, roots) in docs.items():

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\document\document.py:752, in Document.to_json(self, deferred)
    750 serializer = Serializer(deferred=deferred)
    751 defs = serializer.encode(data_models)
--> 752 roots = serializer.encode(self._roots)
    753 callbacks = serializer.encode(self.callbacks._js_event_callbacks)
    755 doc_json = DocJson(
    756     version=__version__,
    757     title=self.title,
    758     roots=roots,
    759 )

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:253, in Serializer.encode(self, obj)
    251 self._circular[ident] = obj
    252 try:
--> 253     return self._encode(obj)
    254 finally:
    255     del self._circular[ident]

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:278, in Serializer._encode(self, obj)
    276     return self._encode_tuple(obj)
    277 elif isinstance(obj, list):
--> 278     return self._encode_list(obj)
    279 elif isinstance(obj, set):
    280     return self._encode_set(obj)

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:326, in Serializer._encode_list(self, obj)
    325 def _encode_list(self, obj: list[Any]) -> ArrayRepLike:
--> 326     return [self.encode(item) for item in obj]

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:253, in Serializer.encode(self, obj)
    251 self._circular[ident] = obj
    252 try:
--> 253     return self._encode(obj)
    254 finally:
    255     del self._circular[ident]

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:262, in Serializer._encode(self, obj)
    260 def _encode(self, obj: Any) -> AnyRep:
    261     if isinstance(obj, Serializable):
--> 262         return obj.to_serializable(self)
    263     elif (encoder := self._encoders.get(type(obj))) is not None:
    264         return encoder(obj, self)

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\model\model.py:534, in Model.to_serializable(self, serializer)
    531 def to_serializable(self, serializer: Serializer) -> ObjectRefRep:
    532     serializer.add_ref(self, self.ref)
--> 534     super_rep = super().to_serializable(serializer)
    535     rep = ObjectRefRep(
    536         type="object",
    537         name=super_rep["name"],
    538         id=self.id,
    539     )
    541     attributes = super_rep.get("attributes")

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\has_props.py:417, in HasProps.to_serializable(self, serializer)
    411 rep = ObjectRep(
    412     type="object",
    413     name=self.__qualified_model__,
    414 )
    416 properties = self.properties_with_values(include_defaults=settings.serialize_include_defaults())
--> 417 attributes = {key: serializer.encode(val) for key, val in properties.items()}
    419 if attributes:
    420     rep["attributes"] = attributes

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:253, in Serializer.encode(self, obj)
    251 self._circular[ident] = obj
    252 try:
--> 253     return self._encode(obj)
    254 finally:
    255     del self._circular[ident]

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:278, in Serializer._encode(self, obj)
    276     return self._encode_tuple(obj)
    277 elif isinstance(obj, list):
--> 278     return self._encode_list(obj)
    279 elif isinstance(obj, set):
    280     return self._encode_set(obj)

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:326, in Serializer._encode_list(self, obj)
    325 def _encode_list(self, obj: list[Any]) -> ArrayRepLike:
--> 326     return [self.encode(item) for item in obj]

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:253, in Serializer.encode(self, obj)
    251 self._circular[ident] = obj
    252 try:
--> 253     return self._encode(obj)
    254 finally:
    255     del self._circular[ident]

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:262, in Serializer._encode(self, obj)
    260 def _encode(self, obj: Any) -> AnyRep:
    261     if isinstance(obj, Serializable):
--> 262         return obj.to_serializable(self)
    263     elif (encoder := self._encoders.get(type(obj))) is not None:
    264         return encoder(obj, self)

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\model\model.py:534, in Model.to_serializable(self, serializer)
    531 def to_serializable(self, serializer: Serializer) -> ObjectRefRep:
    532     serializer.add_ref(self, self.ref)
--> 534     super_rep = super().to_serializable(serializer)
    535     rep = ObjectRefRep(
    536         type="object",
    537         name=super_rep["name"],
    538         id=self.id,
    539     )
    541     attributes = super_rep.get("attributes")

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\has_props.py:417, in HasProps.to_serializable(self, serializer)
    411 rep = ObjectRep(
    412     type="object",
    413     name=self.__qualified_model__,
    414 )
    416 properties = self.properties_with_values(include_defaults=settings.serialize_include_defaults())
--> 417 attributes = {key: serializer.encode(val) for key, val in properties.items()}
    419 if attributes:
    420     rep["attributes"] = attributes

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:253, in Serializer.encode(self, obj)
    251 self._circular[ident] = obj
    252 try:
--> 253     return self._encode(obj)
    254 finally:
    255     del self._circular[ident]

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:262, in Serializer._encode(self, obj)
    260 def _encode(self, obj: Any) -> AnyRep:
    261     if isinstance(obj, Serializable):
--> 262         return obj.to_serializable(self)
    263     elif (encoder := self._encoders.get(type(obj))) is not None:
    264         return encoder(obj, self)

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\model\model.py:534, in Model.to_serializable(self, serializer)
    531 def to_serializable(self, serializer: Serializer) -> ObjectRefRep:
    532     serializer.add_ref(self, self.ref)
--> 534     super_rep = super().to_serializable(serializer)
    535     rep = ObjectRefRep(
    536         type="object",
    537         name=super_rep["name"],
    538         id=self.id,
    539     )
    541     attributes = super_rep.get("attributes")

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\has_props.py:417, in HasProps.to_serializable(self, serializer)
    411 rep = ObjectRep(
    412     type="object",
    413     name=self.__qualified_model__,
    414 )
    416 properties = self.properties_with_values(include_defaults=settings.serialize_include_defaults())
--> 417 attributes = {key: serializer.encode(val) for key, val in properties.items()}
    419 if attributes:
    420     rep["attributes"] = attributes

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:253, in Serializer.encode(self, obj)
    251 self._circular[ident] = obj
    252 try:
--> 253     return self._encode(obj)
    254 finally:
    255     del self._circular[ident]

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:282, in Serializer._encode(self, obj)
    280     return self._encode_set(obj)
    281 elif isinstance(obj, dict):
--> 282     return self._encode_dict(obj)
    283 elif isinstance(obj, SimpleNamespace):
    284     return self._encode_struct(obj)

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:343, in Serializer._encode_dict(self, obj)
    339     result = MapRep(type="map")
    340 else:
    341     result = MapRep(
    342         type="map",
--> 343         entries=[(self.encode(key), self.encode(val)) for key, val in obj.items()],
    344     )
    346 return result

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:253, in Serializer.encode(self, obj)
    251 self._circular[ident] = obj
    252 try:
--> 253     return self._encode(obj)
    254 finally:
    255     del self._circular[ident]

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:299, in Serializer._encode(self, obj)
    297     return self._encode_dataclass(obj)
    298 else:
--> 299     return self._encode_other(obj)

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:477, in Serializer._encode_other(self, obj)
    474 if hasattr(obj, "__array__") and isinstance(arr := obj.__array__(), np.ndarray):
    475     return self._encode_ndarray(arr)
--> 477 self.error(f"can't serialize {type(obj)}")

File C:\ProgramData\anaconda3\Lib\site-packages\bokeh\core\serialization.py:480, in Serializer.error(self, message)
    479 def error(self, message: str) -> NoReturn:
--> 480     raise SerializationError(message)

SerializationError: can't serialize <class 'range'>
df1 = pd.read_csv("owid-covid-data.csv")
df1['date'] = pd.to_datetime(df1['date'])
p = figure(width=600, height=250,x_axis_type='datetime')
p.line(source=df1[df1["location"]=="India"], x="date", y="total_cases", \
       color="indigo", line_width=2)
p.line(source=df1[df1["location"]=="United States"] ,x="date", \
       y="total_cases", color="magenta", line_width=2)
show(p)