- Code better by writing high-quality, readable, and well-tested programs; profiling and optimizing your code, and conducting reproducible interactive computing experiments
- Analyze data with Bayesian and frequentist statistics (Pandas, PyMC, and R), and learn from data with machine learning (scikit-learn)
- Gain valuable insights into signals, images, and sounds with SciPy, scikit-image, and OpenCV
- Learn how to write blazingly fast Python programs with NumPy, PyTables, ctypes, Numba, Cython, OpenMP, GPU programming (CUDA and OpenCL), parallel IPython, MPI, and many more
IPython is at the heart of the Python scientific stack. With its widely acclaimed web-based notebook, IPython is today an ideal gateway to data analysis and numerical computing in Python.
IPython Interactive Computing and Visualization Cookbook contains many ready-to-use focused recipes for high-performance scientific computing and data analysis. The first part covers programming techniques, including code quality and reproducibility; code optimization; high-performance computing through dynamic compilation, parallel computing, and graphics card programming. The second part tackles data science, statistics, machine learning, signal and image processing, dynamical systems, and pure and applied mathematics.
Read an Extract from the book
- First, go to https://github.com/handsontable/jquery-handsontable/tree/master/dist.
- Then, download jquery.handsontable.full.css and jquery.handsontable.full.js, and put these two files in ~\.ipython\profile_default\static\custom\.
- In this folder, add the following line in custom.js:
- In this folder, add the following line in custom.css:
- Now, refresh the notebook!
How to do it...
- Let's import a few functions and classes as follows:
In : from IPython.html import widgets from IPython.display import display from IPython.utils.traitlets import Unicode
In : class HandsonTableWidget(widgets.DOMWidget): _view_name = Unicode('HandsonTableView', sync=True) value = Unicode(sync=True)
- render is for the widget initialization
- Now, we have a synchronized table widget that we can already use. However, we would like to integrate it with pandas. To do this, we create a light wrapper around a DataFrame instance. We create two callback functions for synchronizing the pandas object with the IPython widget. Changes in the GUI will automatically trigger a change in DataFrame, but the converse is not true. We'll need to re-display the widget if we change the DataFrame instance in Python:
In : from io import StringIO import numpy as np import pandas as pd In : class HandsonDataFrame(object): def __init__(self, df): self._df = df self._widget = HandsonTableWidget() self._widget.on_trait_change( self._on_data_changed, 'value') self._widget.on_displayed(self._on_displayed) def _on_displayed(self, e): # DataFrame ==> Widget (upon initialization) json = self._df.to_json(orient='values') self._widget.value = json def _on_data_changed(self, e, val): # Widget ==> DataFrame (called every time the # user changes a value in the widget) buf = StringIO(val) self._df = pd.read_json(buf, orient='values') def to_dataframe(self): return self._df def show(self): display(self._widget)
- Now, let's test all that! We first create a random DataFrame instance:
In : data = np.random.randint(size=(3, 5), low=100, high=900) df = pd.DataFrame(data) df Out: 352 201 859 322 352 326 519 848 802 642 171 480 213 619 192
- We wrap it in HandsonDataFrame and show it as follows:
In : ht = HandsonDataFrame(df) ht.show()
- We can now change the values interactively, and they will be changed in Python accordingly:
In : ht.to_dataframe() Out: 352 201 859 322 352 326 519 848 1024 642 171 480 213 619 192
How it works...
callback() callback(trait_name) callback(trait_name, new_value) callback(trait_name, old_value, new_value)
The following are the ways this proof-of-concept could be improved:
- Synchronizing only changes instead of synchronizing the whole array every time
(the method used here would be slow on large tables)
- Avoiding recreating a new DataFrame instance upon every change, but updating the same DataFrame instance in-place
- Supporting named columns
- Hiding the wrapper, that is, make it so that the default rich representation of DataFrame in the notebook is HandsonDataFrame
- Implementing everything in an easy-to-use extension
Here are a few references about the widget architecture in the IPython notebook 2.0+: