from __future__ import print_function # For py 2.7 compat
from IPython.html import widgets # Widget definitions
from IPython.display import display # Used to display widgets in the notebook
from IPython.utils.traitlets import Unicode # Used to declare attributes of our widget
class HandsonTableWidget(widgets.DOMWidget):
_view_name = Unicode('HandsonTableView', sync=True)
value = Unicode(sync=True)
%%javascript
var table_id = 0;
require(["widgets/js/widget"], function(WidgetManager){
// Define the HandsonTableView
var HandsonTableView = IPython.DOMWidgetView.extend({
render: function(){
// CREATION OF THE WIDGET IN THE NOTEBOOK.
// Add a
in the widget area.
this.$table = $('
')
.attr('id', 'table_' + (table_id++))
.appendTo(this.$el);
// Create the Handsontable table.
this.$table.handsontable({
});
},
update: function() {
// PYTHON --> JS UPDATE.
// Get the model's JSON string, and parse it.
var data = $.parseJSON(this.model.get('value'));
// Give it to the Handsontable widget.
this.$table.handsontable({data: data});
// Don't touch this...
return HandsonTableView.__super__.update.apply(this);
},
// Tell Backbone to listen to the change event of input controls.
events: {"change": "handle_table_change"},
handle_table_change: function(event) {
// JS --> PYTHON UPDATE.
// Get the table instance.
var ht = this.$table.handsontable('getInstance');
// Get the data, and serialize it in JSON.
var json = JSON.stringify(ht.getData());
// Update the model with the JSON string.
this.model.set('value', json);
// Don't touch this...
this.touch();
},
});
// Register the HandsonTableView with the widget manager.
WidgetManager.register_widget_view('HandsonTableView', HandsonTableView);
});
import StringIO
import numpy as np
import pandas as pd
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 only)
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 graphical widget)
buf = StringIO.StringIO(val)
self._df = pd.read_json(buf, orient='values')
def to_dataframe(self):
return self._df
def show(self):
display(self._widget)
data = np.random.randint(size=(3, 5), low=100, high=900)
df = pd.DataFrame(data)
df
ht = HandsonDataFrame(df)
ht.show()
ht.to_dataframe()