Using JQuery DataTables with IPython
28 Aug 2014
|
~
4 mins
|
tags: [ ipython python jquery javascript ]
I thought this might be interesting enough to share with you. Every time I’m working with DataFrames I somehow miss the search feature: I’d like to search for certain patterns inside the columns and rows. I used to use JQuery DataTables for netgrafio . But I couldn’t find any simple way to integrate it with IPython. Well it was easier than I thought.
Extensions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# <!-- collapse=True -->
from IPython import display
from IPython.core.magic import register_cell_magic, Magics, magics_class, cell_magic
import jinja2
# Create jinja cell magic (http://nbviewer.ipython.org/urls/gist.github.com/bj0/5343292/raw/23a0845ee874827e3635edb0bf5701710a537bfc/jinja2.ipynb)
@magics_class
class JinjaMagics(Magics):
'''Magics class containing the jinja2 magic and state'''
def __init__(self, shell):
super(JinjaMagics, self).__init__(shell)
# create a jinja2 environment to use for rendering
# this can be modified for desired effects (ie: using different variable syntax)
self.env = jinja2.Environment(loader=jinja2.FileSystemLoader('.'))
# possible output types
self.display_functions = dict(html=display.HTML,
latex=display.Latex,
json=display.JSON,
pretty=display.Pretty,
display=display.display)
@cell_magic
def jinja(self, line, cell):
'''
jinja2 cell magic function. Contents of cell are rendered by jinja2, and
the line can be used to specify output type.
ie: "%%jinja html" will return the rendered cell wrapped in an HTML object.
'''
f = self.display_functions.get(line.lower().strip(), display.display)
tmp = self.env.from_string(cell)
rend = tmp.render(dict((k,v) for (k,v) in self.shell.user_ns.items()
if not k.startswith('_') and k not in self.shell.user_ns_hidden))
return f(rend)
ip = get_ipython()
ip.register_magics(JinjaMagics)
DataTable function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# <!-- collapse=True -->
import uuid
def DataTable(df):
""" Prints a pandas.DataFrame as JQuery DataTables """
from IPython.display import HTML
# Generate random container name
id_container = uuid.uuid1()
output = """
<div id="datatable-container-%s">
<link rel="stylesheet" type="text/css" href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/css/jquery.dataTables.css">
<link rel="stylesheet" type="text/css" href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/css/jquery.dataTables_themeroller.css">
<script type="text/javascript" charset="utf8" src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/jquery.dataTables.min.js"></script>
<script type="text/javascript">
var url = window.location.href;
if(url.indexOf("localhost:9999") != -1){
$('#datatable-container-%s table.datatable').dataTable();
} else {
$.getScript("http://code.jquery.com/jquery-1.11.1.min.js");
$(document).ready(function() {
$('#datatable-container-%s table.datatable').dataTable();
});
}
</script>
<!-- Insert table below -->
%s
</div>
""" % (id_container, id_container, id_container, df.to_html(index=False, classes="datatable dataframe"))
return HTML(output)
I know the code is not perfect, but at least it works for me. Now let’s create some random DataFrame:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import pandas as pd
import urllib2
from yurl import URL
# Fetch list of random URLs (found using Google)
response = urllib2.urlopen('http://files.ianonavy.com/urls.txt')
targets_row = response.read()
# Create DataFrame
targets = pd.DataFrame([t for t in targets_row.splitlines()], columns=["Target"])
# Join root domain + suffix
extract_root_domain = lambda x: '.'.join(tldextract.extract(x)[1:3])
target_columns = ['scheme', 'userinfo', 'host', 'port', 'path', 'query', 'fragment', 'decoded']
target_component = [list(URL(t)) for t in targets['Target']]
# Create data frame
df_targets = pd.DataFrame(target_component, columns=target_columns)
Classic HTML output
scheme
userinfo
host
port
path
query
fragment
decoded
0
http
www.altpress.org
/
False
1
http
www.nzfortress.co.nz
False
2
http
www.evillasforsale.com
False
3
http
www.playingenemy.com
/
False
4
http
www.richardsonscharts.com
False
5
http
www.xenith.net
False
6
http
www.tdbrecords.com
False
7
http
www.electrichumanproject.com
/
False
8
http
tweekerchick.blogspot.com
/
False
9
http
www.besound.com
/pushead/home.html
False
10
http
www.porkchopscreenprinting.com
/
False
11
http
www.kinseyvisual.com
False
12
http
www.rathergood.com
False
13
http
www.lepoint.fr
/
False
14
http
www.revhq.com
False
15
http
www.poprocksandcoke.com
False
16
http
www.samuraiblue.com
/
False
17
http
www.openbsd.org
/cgi-bin/man.cgi
False
18
http
www.sysblog.com
False
19
http
www.voicesofsafety.com
False
JQuery DataTables output
1
DataTable(df_targets[:20])
<div id="datatable-container-aab341ae-2f8d-11e4-95d5-52540086692e">
<link rel="stylesheet" type="text/css" href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/css/jquery.dataTables.css">
<link rel="stylesheet" type="text/css" href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/css/jquery.dataTables_themeroller.css">
<script type="text/javascript" charset="utf8" src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/jquery.dataTables.min.js"></script>
<script type="text/javascript">
var url = window.location.href;
if(url.indexOf("localhost:9999") != -1){
$('#datatable-container-aab341ae-2f8d-11e4-95d5-52540086692e table.datatable').dataTable();
} else {
$.getScript("http://code.jquery.com/jquery-1.11.1.min.js");
$(document).ready(function() {
$('#datatable-container-aab341ae-2f8d-11e4-95d5-52540086692e table.datatable').dataTable();
});
}
</script>
<!-- Insert table below -->
<table border="1" class="dataframe datatable dataframe">
scheme
userinfo
host
port
path
query
fragment
decoded
http
www.altpress.org
/
False
http
www.nzfortress.co.nz
False
http
www.evillasforsale.com
False
http
www.playingenemy.com
/
False
http
www.richardsonscharts.com
False
http
www.xenith.net
False
http
www.tdbrecords.com
False
http
www.electrichumanproject.com
/
False
http
tweekerchick.blogspot.com
/
False
http
www.besound.com
/pushead/home.html
False
http
www.porkchopscreenprinting.com
/
False
http
www.kinseyvisual.com
False
http
www.rathergood.com
False
http
www.lepoint.fr
/
False
http
www.revhq.com
False
http
www.poprocksandcoke.com
False
http
www.samuraiblue.com
/
False
http
www.openbsd.org
/cgi-bin/man.cgi
False
http
www.sysblog.com
False
http
www.voicesofsafety.com
False
Jinja2 cellmagic
1
html_output = DataTable(df_targets[:20])
1
2
3
4
%%jinja html
<div id="table-container">
{{ html_output }}
</div>
<div id="datatable-container-3b6a2692-2f8c-11e4-95d5-52540086692e">
<link rel="stylesheet" type="text/css" href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/css/jquery.dataTables.css">
<link rel="stylesheet" type="text/css" href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/css/jquery.dataTables_themeroller.css">
<script type="text/javascript" charset="utf8" src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/jquery.dataTables.min.js"></script>
<script type="text/javascript">
$('#datatable-container-3b6a2692-2f8c-11e4-95d5-52540086692e table.datatable').dataTable();
</script>
<!-- Insert table below -->
<table border="1" class="dataframe datatable dataframe">
scheme
userinfo
host
port
path
query
fragment
decoded
http
www.altpress.org
/
False
http
www.nzfortress.co.nz
False
http
www.evillasforsale.com
False
http
www.playingenemy.com
/
False
http
www.richardsonscharts.com
False
http
www.xenith.net
False
http
www.tdbrecords.com
False
http
www.electrichumanproject.com
/
False
http
tweekerchick.blogspot.com
/
False
http
www.besound.com
/pushead/home.html
False
http
www.porkchopscreenprinting.com
/
False
http
www.kinseyvisual.com
False
http
www.rathergood.com
False
http
www.lepoint.fr
/
False
http
www.revhq.com
False
http
www.poprocksandcoke.com
False
http
www.samuraiblue.com
/
False
http
www.openbsd.org
/cgi-bin/man.cgi
False
http
www.sysblog.com
False
http
www.voicesofsafety.com
False
Easy isn’t it? Thx for sharing.