Created
January 5, 2016 06:12
-
-
Save bicubic/1671473d59d2fa73aef7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"#qgrid - SlickGrid in IPython notebook\n", | |
"---" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Qgrid is an IPython extension which uses a javascript library called SlickGrid to render pandas DataFrames within an IPython notebook. It's being developed for use in [Quantopian's hosted research environment]( https://www.quantopian.com/research?utm_source=github&utm_medium=web&utm_campaign=qgrid-nbviewer), and this notebook demonstrates the current state of the project." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Overview\n", | |
"* [SlickGrid](https://github.com/mleibman/SlickGrid) is an an advanced javascript grid which allows users to scroll, sort, \n", | |
"and filter hundreds of thousands of rows with extreme responsiveness. \n", | |
"* [Pandas](https://github.com/pydata/pandas) is a powerful data analysis / manipulation library for Python, and DataFrames are the primary way of storing and manipulating two-dimensional data in pandas.\n", | |
"\n", | |
"[Qgrid](https://github.com/quantopian/qgrid) renders pandas DataFrames as SlickGrids, which enables users to explore the entire contents of a DataFrame using intuitive sorting and filtering controls. It's designed to be used within IPython notebook, and it's also fully functional when rendered in [nbviewer](http://nbviewer.ipython\n", | |
".org/github/quantopian/qgrid/blob/master/qgrid_demo.ipynb)." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Installation using 'pip install'\n", | |
"##### Qgrid is a python module so you can install it using pip:\n", | |
"\n", | |
"```pip install git+https://github.com/quantopian/qgrid```\n", | |
"\n", | |
"##### Import it into your namespace like you would for any other python module:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"import qgrid" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"##### Prepare non-python dependencies by calling \"`nbinstall`\":" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"qgrid.nbinstall(overwrite=True) # copies javascript dependencies to your /nbextensions folder " | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"##### Set default options by calling \"set_defaults\" (optional):" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"qgrid.set_defaults(remote_js=True, precision=4)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Demo 1 - Rendering a DataFrame returned by Yahoo Finance\n", | |
"##### First, lets create a sample DataFrame using pandas 'get_data_yahoo' function:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"C:\\Anaconda2\\lib\\site-packages\\pandas\\io\\data.py:33: FutureWarning: \n", | |
"The pandas.io.data module is moved to a separate package (pandas-datareader) and will be removed from pandas in a future version.\n", | |
"After installing the pandas-datareader package (https://github.com/pydata/pandas-datareader), you can change the import ``from pandas.io import data, wb`` to ``from pandas_datareader import data, wb``.\n", | |
" FutureWarning)\n" | |
] | |
} | |
], | |
"source": [ | |
"import pandas as pd\n", | |
"import numpy as np\n", | |
"randn = np.random.randn\n", | |
"\n", | |
"pd.set_option('display.max_rows', 8)\n", | |
"\n", | |
"from pandas.io.data import get_data_yahoo\n", | |
"spy = get_data_yahoo(\n", | |
" symbols='SPY',\n", | |
" start=pd.Timestamp('2011-01-01'),\n", | |
" end=pd.Timestamp('2014-01-01'),\n", | |
" adjust_price=True,\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"##### BEFORE - Here's IPython's default representation of our 'spy' DataFrame:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>Open</th>\n", | |
" <th>High</th>\n", | |
" <th>Low</th>\n", | |
" <th>Close</th>\n", | |
" <th>Volume</th>\n", | |
" <th>Adj_Ratio</th>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>Date</th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>2011-01-03</th>\n", | |
" <td>114.369788</td>\n", | |
" <td>115.173110</td>\n", | |
" <td>113.458149</td>\n", | |
" <td>114.676679</td>\n", | |
" <td>138725200</td>\n", | |
" <td>0.902611</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2011-01-04</th>\n", | |
" <td>114.929410</td>\n", | |
" <td>114.965515</td>\n", | |
" <td>113.900434</td>\n", | |
" <td>114.613497</td>\n", | |
" <td>137409700</td>\n", | |
" <td>0.902611</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2011-01-05</th>\n", | |
" <td>114.252451</td>\n", | |
" <td>115.281427</td>\n", | |
" <td>114.144135</td>\n", | |
" <td>115.209216</td>\n", | |
" <td>133975300</td>\n", | |
" <td>0.902611</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2011-01-06</th>\n", | |
" <td>115.254350</td>\n", | |
" <td>115.380715</td>\n", | |
" <td>114.640575</td>\n", | |
" <td>114.983564</td>\n", | |
" <td>122519000</td>\n", | |
" <td>0.902611</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>...</th>\n", | |
" <td>...</td>\n", | |
" <td>...</td>\n", | |
" <td>...</td>\n", | |
" <td>...</td>\n", | |
" <td>...</td>\n", | |
" <td>...</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2013-12-26</th>\n", | |
" <td>176.190385</td>\n", | |
" <td>176.786218</td>\n", | |
" <td>176.171176</td>\n", | |
" <td>176.690112</td>\n", | |
" <td>63365000</td>\n", | |
" <td>0.961004</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2013-12-27</th>\n", | |
" <td>176.920758</td>\n", | |
" <td>176.997626</td>\n", | |
" <td>176.497914</td>\n", | |
" <td>176.680507</td>\n", | |
" <td>61814000</td>\n", | |
" <td>0.961004</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2013-12-30</th>\n", | |
" <td>176.699717</td>\n", | |
" <td>176.843876</td>\n", | |
" <td>176.421032</td>\n", | |
" <td>176.651678</td>\n", | |
" <td>56857000</td>\n", | |
" <td>0.961004</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2013-12-31</th>\n", | |
" <td>176.891930</td>\n", | |
" <td>177.487747</td>\n", | |
" <td>176.757376</td>\n", | |
" <td>177.487747</td>\n", | |
" <td>86119900</td>\n", | |
" <td>0.961004</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"<p>754 rows × 6 columns</p>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Open High Low Close Volume \\\n", | |
"Date \n", | |
"2011-01-03 114.369788 115.173110 113.458149 114.676679 138725200 \n", | |
"2011-01-04 114.929410 114.965515 113.900434 114.613497 137409700 \n", | |
"2011-01-05 114.252451 115.281427 114.144135 115.209216 133975300 \n", | |
"2011-01-06 115.254350 115.380715 114.640575 114.983564 122519000 \n", | |
"... ... ... ... ... ... \n", | |
"2013-12-26 176.190385 176.786218 176.171176 176.690112 63365000 \n", | |
"2013-12-27 176.920758 176.997626 176.497914 176.680507 61814000 \n", | |
"2013-12-30 176.699717 176.843876 176.421032 176.651678 56857000 \n", | |
"2013-12-31 176.891930 177.487747 176.757376 177.487747 86119900 \n", | |
"\n", | |
" Adj_Ratio \n", | |
"Date \n", | |
"2011-01-03 0.902611 \n", | |
"2011-01-04 0.902611 \n", | |
"2011-01-05 0.902611 \n", | |
"2011-01-06 0.902611 \n", | |
"... ... \n", | |
"2013-12-26 0.961004 \n", | |
"2013-12-27 0.961004 \n", | |
"2013-12-30 0.961004 \n", | |
"2013-12-31 0.961004 \n", | |
"\n", | |
"[754 rows x 6 columns]" | |
] | |
}, | |
"execution_count": 5, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"spy" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"##### AFTER - Here's the same 'spy' DataFrame being rendered as a qgrid:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"qgrid.show_grid(spy)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"##### Configuring your grid using SlickGrid options\n", | |
"By default, columns are stretched to fill the full width of the grid area. That doesn't work if you have hundreds of columns, so you can change this behavior by using the `forceFitColumns` and `defaultColumnWidth` SlickGrid options. See https://github.com/mleibman/SlickGrid/wiki/Grid-Options for the full list of SlickGrid options that you can configure:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": false | |
}, | |
"outputs": [], | |
"source": [ | |
"qgrid.show_grid(spy, grid_options={'forceFitColumns': False, 'defaultColumnWidth': 200})" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Demo 2 - Rendering a sample DataFrame that includes a MultiIndex\n", | |
"##### Now let's create another DataFrame, but let's give it a MultiIndex this time:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"tuples = list(zip(*[['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],\n", | |
" ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]))\n", | |
"\n", | |
"\n", | |
"index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])\n", | |
"multi_index_df = pd.DataFrame(randn(8, 2), index=index, columns=['A', 'B'])" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"##### BEFORE - Here's IPython's default representation of our 'multi_index_df' DataFrame:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th>A</th>\n", | |
" <th>B</th>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>first</th>\n", | |
" <th>second</th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th rowspan=\"2\" valign=\"top\">bar</th>\n", | |
" <th>one</th>\n", | |
" <td>-0.575530</td>\n", | |
" <td>1.427808</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>two</th>\n", | |
" <td>0.375397</td>\n", | |
" <td>-0.875816</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th rowspan=\"2\" valign=\"top\">baz</th>\n", | |
" <th>one</th>\n", | |
" <td>-0.004922</td>\n", | |
" <td>0.577942</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>two</th>\n", | |
" <td>0.687730</td>\n", | |
" <td>0.146175</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th rowspan=\"2\" valign=\"top\">foo</th>\n", | |
" <th>one</th>\n", | |
" <td>0.229348</td>\n", | |
" <td>0.226755</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>two</th>\n", | |
" <td>-0.935726</td>\n", | |
" <td>-0.464503</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th rowspan=\"2\" valign=\"top\">qux</th>\n", | |
" <th>one</th>\n", | |
" <td>1.242928</td>\n", | |
" <td>-0.168419</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>two</th>\n", | |
" <td>0.166165</td>\n", | |
" <td>0.524975</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" A B\n", | |
"first second \n", | |
"bar one -0.575530 1.427808\n", | |
" two 0.375397 -0.875816\n", | |
"baz one -0.004922 0.577942\n", | |
" two 0.687730 0.146175\n", | |
"foo one 0.229348 0.226755\n", | |
" two -0.935726 -0.464503\n", | |
"qux one 1.242928 -0.168419\n", | |
" two 0.166165 0.524975" | |
] | |
}, | |
"execution_count": 9, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"multi_index_df" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"##### AFTER - Here's the same 'multi_index_df' DataFrame being rendered as a qgrid:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"qgrid.show_grid(multi_index_df)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## API & Usage\n", | |
"API documentation is hosted on readthedocs: http://qgrid.readthedocs.org/en/latest/\n", | |
"\n", | |
"The API documentation can also be accessed via the \"?\" operator in IPython. To use the \"?\" operator, type the name of the function followed by \"?\" to see the documentation for that function, like this:\n", | |
"```\n", | |
"qgrid.nbinstall?\n", | |
"qgrid.show_grid?\n", | |
"qgrid.set_defaults?\n", | |
"qgrid.set_grid_options?\n", | |
"\n", | |
"```" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Running from source using 'git clone'\n", | |
"##### Use git to clone the qgrid repository to your hard drive\n", | |
"`git clone [email protected]:quantopian/qgrid.git`\n", | |
"##### Set the root folder of your qgrid repository to be the working directory for your IPython notebook server\n", | |
"This is an easy way to get qgrid to run directly from the source code. IPython notebook will look in it's working directory for modules to load, so qgrid will immediately become available for importing.\n", | |
"\n", | |
"`ipython notebook --notebook-dir=~/path/to/qgrid/repo`\n", | |
"\n", | |
"It's not always convenient to use the qgrid repository as your working directory for IPython noteboook, so I often create symbolic-links from qgrid's source code into the \"/nbextensions\" and \"/extensions\" folders under my IPython directory.\n", | |
"\n", | |
"\n", | |
"##### Import it into your namespace like you would for any other python module:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"import qgrid" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"##### Prepare non-python dependencies by calling 'nbinstall':" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"qgrid.nbinstall(overwrite=True) # use overwrite=True to keep your /nbextensions folder up to date during development" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 2", | |
"language": "python", | |
"name": "python2" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 2 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython2", | |
"version": "2.7.11" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment