Skip to content

Instantly share code, notes, and snippets.

@mgymrek
Created January 12, 2014 19:05
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mgymrek/8388937 to your computer and use it in GitHub Desktop.
Save mgymrek/8388937 to your computer and use it in GitHub Desktop.
Making formatted tables for IPython notebooks
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"name": ""
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I've been working on making presentations in IPython lately. I often end up using tables in my presentations and publications, and wanted a way to format them nicely from IPython notebooks. So I added the PrettyTable class, along with some basic themes, to [my fork of ipywidgets](https://github.com/mgymrek/ipywidgets). This allows for easily formatting the way tables are displayed. This is similar in spirit to the [ipy_table](http://github.com/epmoyer/ipy_table/) repository, but with more modular themes and the ability to add any property to tables that you can do with CSS.\n",
"\n",
"Getting started\n",
"===============\n",
"Here's an example of how it works to get started. To create a PrettyTable, import ipywidgets and pass a pandas data frame:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from ipywidgets import *\n",
"import pandas as pd\n",
"df = pd.DataFrame({\"x\":[1,2,3], \"y\":[6,4,3], \"z\":[\"testing\",\"pretty\",\"tables\"], \"f\":[0.023432, 0.234321,0.5555]})\n",
"pt = PrettyTable(df)\n",
"pt"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<table style=\"\"><tr style=\"\"><td style=\"\">f</td><td style=\"\">x</td><td style=\"\">y</td><td style=\"\">z</td></tr><tr style=\"\"><td style=\"\">0.023432</td><td style=\"\">1</td><td style=\"\">6</td><td style=\"\">testing</td></tr><tr style=\"\"><td style=\"\">0.234321</td><td style=\"\">2</td><td style=\"\">4</td><td style=\"\">pretty</td></tr><tr style=\"\"><td style=\"\">0.5555</td><td style=\"\">3</td><td style=\"\">3</td><td style=\"\">tables</td></tr></table>"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 1,
"text": [
"<ipywidgets.pretty_table.PrettyTable at 0x4524cd0>"
]
}
],
"prompt_number": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can make it a little bit prettier by giving it a style theme and centering the table:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"pt = PrettyTable(df, tstyle=TableStyle(theme=\"theme1\"), center=True)\n",
"pt"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<center><table style=\"color: black;border: 1px solid black;\"><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;font-weight: bold;background-color: lightgray;\">f</td><td style=\"color: black;font-weight: bold;background-color: lightgray;\">x</td><td style=\"color: black;font-weight: bold;background-color: lightgray;\">y</td><td style=\"color: black;font-weight: bold;background-color: lightgray;\">z</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;border: 1px solid black;\">0.023432</td><td style=\"color: black;border: 1px solid black;\">1</td><td style=\"color: black;border: 1px solid black;\">6</td><td style=\"color: black;border: 1px solid black;\">testing</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;border: 1px solid black;\">0.234321</td><td style=\"color: black;border: 1px solid black;\">2</td><td style=\"color: black;border: 1px solid black;\">4</td><td style=\"color: black;border: 1px solid black;\">pretty</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;border: 1px solid black;\">0.5555</td><td style=\"color: black;border: 1px solid black;\">3</td><td style=\"color: black;border: 1px solid black;\">3</td><td style=\"color: black;border: 1px solid black;\">tables</td></tr></table></center>"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 2,
"text": [
"<ipywidgets.pretty_table.PrettyTable at 0x4524a10>"
]
}
],
"prompt_number": 2
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are many options for formatting and styling, described below."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Setting cell styles\n",
"\n",
"You can set cell styles by passing ```PrettyTable.set_cell_style``` a ```CellStyle``` object, or by specifying CSS properties. You can tell ```set_cell_style``` a specific set of rows and columns to apply the style to with the arguments ```rows=``` and ```cols=```. Or leave those arguments blank to apply to all rows/columns:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Set cell style using a CellStyle object\n",
"pt = PrettyTable(df, tstyle=TableStyle(theme=\"theme1\"), center=True)\n",
"cs = CellStyle()\n",
"cs.set(\"background-color\", \"red\")\n",
"cs.set(\"color\", \"white\")\n",
"pt.set_cell_style(style=cs)\n",
"pt"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<center><table style=\"color: black;border: 1px solid black;\"><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;font-weight: bold;background-color: lightgray;\">f</td><td style=\"color: black;font-weight: bold;background-color: lightgray;\">x</td><td style=\"color: black;font-weight: bold;background-color: lightgray;\">y</td><td style=\"color: black;font-weight: bold;background-color: lightgray;\">z</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: white;background-color: red;\">0.023432</td><td style=\"color: white;background-color: red;\">1</td><td style=\"color: white;background-color: red;\">6</td><td style=\"color: white;background-color: red;\">testing</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: white;background-color: red;\">0.234321</td><td style=\"color: white;background-color: red;\">2</td><td style=\"color: white;background-color: red;\">4</td><td style=\"color: white;background-color: red;\">pretty</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: white;background-color: red;\">0.5555</td><td style=\"color: white;background-color: red;\">3</td><td style=\"color: white;background-color: red;\">3</td><td style=\"color: white;background-color: red;\">tables</td></tr></table></center>"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 3,
"text": [
"<ipywidgets.pretty_table.PrettyTable at 0x4d84890>"
]
}
],
"prompt_number": 3
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Only for a subset of rows/columns\n",
"pt = PrettyTable(df, tstyle=TableStyle(theme=\"theme1\"), center=True)\n",
"cs = CellStyle()\n",
"cs.set(\"background-color\", \"red\")\n",
"cs.set(\"color\", \"white\")\n",
"pt.set_cell_style(style=cs, rows=[1,2], cols=[2])\n",
"pt"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<center><table style=\"color: black;border: 1px solid black;\"><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;font-weight: bold;background-color: lightgray;\">f</td><td style=\"color: black;font-weight: bold;background-color: lightgray;\">x</td><td style=\"color: black;font-weight: bold;background-color: lightgray;\">y</td><td style=\"color: black;font-weight: bold;background-color: lightgray;\">z</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;border: 1px solid black;\">0.023432</td><td style=\"color: black;border: 1px solid black;\">1</td><td style=\"color: black;border: 1px solid black;\">6</td><td style=\"color: black;border: 1px solid black;\">testing</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;border: 1px solid black;\">0.234321</td><td style=\"color: black;border: 1px solid black;\">2</td><td style=\"color: white;background-color: red;\">4</td><td style=\"color: black;border: 1px solid black;\">pretty</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;border: 1px solid black;\">0.5555</td><td style=\"color: black;border: 1px solid black;\">3</td><td style=\"color: white;background-color: red;\">3</td><td style=\"color: black;border: 1px solid black;\">tables</td></tr></table></center>"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 4,
"text": [
"<ipywidgets.pretty_table.PrettyTable at 0x4d8c710>"
]
}
],
"prompt_number": 4
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Set styles using keywords (these are all CSS properties, just replace \"-\" with \"_\")\n",
"pt = PrettyTable(df, tstyle=TableStyle(theme=\"theme1\"), center=True)\n",
"pt.set_cell_style(font_weight=\"bold\", color=\"purple\", background_color=\"yellow\", rows=[1], cols=[2,3])\n",
"pt"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<center><table style=\"color: black;border: 1px solid black;\"><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;font-weight: bold;background-color: lightgray;\">f</td><td style=\"color: black;font-weight: bold;background-color: lightgray;\">x</td><td style=\"color: black;font-weight: bold;background-color: lightgray;\">y</td><td style=\"color: black;font-weight: bold;background-color: lightgray;\">z</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;border: 1px solid black;\">0.023432</td><td style=\"color: black;border: 1px solid black;\">1</td><td style=\"color: black;border: 1px solid black;\">6</td><td style=\"color: black;border: 1px solid black;\">testing</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;border: 1px solid black;\">0.234321</td><td style=\"color: black;border: 1px solid black;\">2</td><td style=\"color: purple;font-weight: bold;background-color: yellow;\">4</td><td style=\"color: purple;font-weight: bold;background-color: yellow;\">pretty</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;border: 1px solid black;\">0.5555</td><td style=\"color: black;border: 1px solid black;\">3</td><td style=\"color: black;border: 1px solid black;\">3</td><td style=\"color: black;border: 1px solid black;\">tables</td></tr></table></center>"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 5,
"text": [
"<ipywidgets.pretty_table.PrettyTable at 0x4524b50>"
]
}
],
"prompt_number": 5
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can do the same thing for row/header styles using ```set_row_header_style``` and ```set_col_header_style``` (and ```set_corner_style``` for the awkward corner cell in the case of both row and column headings). Use the ```indices=``` argument to only apply to certain headings."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"pt = PrettyTable(df, tstyle=TableStyle(theme=\"theme1\"), center=True, header_row=True)\n",
"pt.set_row_header_style(color=\"blue\")\n",
"pt.set_col_header_style(background_color=\"white\", font_weight=\"bold\", indices=[2])\n",
"pt.set_corner_style(background_color=\"red\")\n",
"pt"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<center><table style=\"color: black;border: 1px solid black;\"><tr style=\"color: black;border: 1px solid black;\"><td style=\"background-color: red;\"></td><td style=\"color: black;font-weight: bold;background-color: lightgray;\">f</td><td style=\"color: black;font-weight: bold;background-color: lightgray;\">x</td><td style=\"font-weight: bold;background-color: white;\">y</td><td style=\"color: black;font-weight: bold;background-color: lightgray;\">z</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: blue;\">0</td><td style=\"color: black;border: 1px solid black;\">0.023432</td><td style=\"color: black;border: 1px solid black;\">1</td><td style=\"color: black;border: 1px solid black;\">6</td><td style=\"color: black;border: 1px solid black;\">testing</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: blue;\">1</td><td style=\"color: black;border: 1px solid black;\">0.234321</td><td style=\"color: black;border: 1px solid black;\">2</td><td style=\"color: black;border: 1px solid black;\">4</td><td style=\"color: black;border: 1px solid black;\">pretty</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: blue;\">2</td><td style=\"color: black;border: 1px solid black;\">0.5555</td><td style=\"color: black;border: 1px solid black;\">3</td><td style=\"color: black;border: 1px solid black;\">3</td><td style=\"color: black;border: 1px solid black;\">tables</td></tr></table></center>"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 6,
"text": [
"<ipywidgets.pretty_table.PrettyTable at 0x4d8cfd0>"
]
}
],
"prompt_number": 6
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sometimes you may just want to *update* the style of a cell, rather than starting over. There are also functions to do this. They behave the same way as the \"set style\" functions described above, except they just add to the existing style:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"pt = PrettyTable(df, tstyle=TableStyle(theme=\"theme1\"), center=True, header_row=True)\n",
"pt.set_cell_style(font_weight=\"bold\", color=\"purple\", background_color=\"yellow\", rows=[1], cols=[2,3])\n",
"pt.update_cell_style(background_color=\"pink\", rows=[1], cols=[3])\n",
"pt.update_row_header_style(background_color=\"blue\", indices=[0])\n",
"pt.update_col_header_style(color=\"red\")\n",
"pt.update_corner_style(background_color=\"purple\")\n",
"pt"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<center><table style=\"color: black;border: 1px solid black;\"><tr style=\"color: black;border: 1px solid black;\"><td style=\"background-color: purple;\"></td><td style=\"color: red;font-weight: bold;background-color: lightgray;\">f</td><td style=\"color: red;font-weight: bold;background-color: lightgray;\">x</td><td style=\"color: red;font-weight: bold;background-color: lightgray;\">y</td><td style=\"color: red;font-weight: bold;background-color: lightgray;\">z</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;font_weight: bold;background-color: blue;\">0</td><td style=\"color: black;border: 1px solid black;\">0.023432</td><td style=\"color: black;border: 1px solid black;\">1</td><td style=\"color: black;border: 1px solid black;\">6</td><td style=\"color: black;border: 1px solid black;\">testing</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;font_weight: bold;background-color: lightgray;\">1</td><td style=\"color: black;border: 1px solid black;\">0.234321</td><td style=\"color: black;border: 1px solid black;\">2</td><td style=\"color: purple;font-weight: bold;background-color: yellow;\">4</td><td style=\"color: purple;font-weight: bold;background-color: pink;\">pretty</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;font_weight: bold;background-color: lightgray;\">2</td><td style=\"color: black;border: 1px solid black;\">0.5555</td><td style=\"color: black;border: 1px solid black;\">3</td><td style=\"color: black;border: 1px solid black;\">3</td><td style=\"color: black;border: 1px solid black;\">tables</td></tr></table></center>"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 7,
"text": [
"<ipywidgets.pretty_table.PrettyTable at 0x4d8d250>"
]
}
],
"prompt_number": 7
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, there are a set of \"reset style\" functions to reset the styles of cells, headings, and corner cells."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"pt = PrettyTable(df, tstyle=TableStyle(theme=\"theme1\"), center=True, header_row=True)\n",
"pt.set_cell_style(font_weight=\"bold\", color=\"purple\", background_color=\"yellow\", rows=[1], cols=[2,3])\n",
"pt.reset_cell_style(rows=[1], cols=[2])\n",
"pt.reset_row_header_style(indices=[1])\n",
"pt.reset_col_header_style()\n",
"pt"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<center><table style=\"color: black;border: 1px solid black;\"><tr style=\"color: black;border: 1px solid black;\"><td style=\"\"></td><td style=\"\">f</td><td style=\"\">x</td><td style=\"\">y</td><td style=\"\">z</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;font_weight: bold;background-color: lightgray;\">0</td><td style=\"color: black;border: 1px solid black;\">0.023432</td><td style=\"color: black;border: 1px solid black;\">1</td><td style=\"color: black;border: 1px solid black;\">6</td><td style=\"color: black;border: 1px solid black;\">testing</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"\">1</td><td style=\"color: black;border: 1px solid black;\">0.234321</td><td style=\"color: black;border: 1px solid black;\">2</td><td style=\"\">4</td><td style=\"color: purple;font-weight: bold;background-color: yellow;\">pretty</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;font_weight: bold;background-color: lightgray;\">2</td><td style=\"color: black;border: 1px solid black;\">0.5555</td><td style=\"color: black;border: 1px solid black;\">3</td><td style=\"color: black;border: 1px solid black;\">3</td><td style=\"color: black;border: 1px solid black;\">tables</td></tr></table></center>"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 8,
"text": [
"<ipywidgets.pretty_table.PrettyTable at 0x4524090>"
]
}
],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Setting cell formats\n",
"\n",
"You can also pass the functions shown above an argument ```format_function```, which will tell the PrettyTable how to display the data. By default, it will call the ```str``` of each method. For instance, maybe you have a column of floats you want rounded to 3 decimal places, and another column you'd like to have in scientific notation:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"df = pd.DataFrame({\"FloatColumn\": [0.0324234, 0.23432111, 0.555555], \"SciNotColumn\":[1e10, 4.232e-6, 53e-8]})\n",
"pt = PrettyTable(df, tstyle=TableStyle(theme=\"theme1\"), center=True)\n",
"pt.set_cell_style(cols=[0], format_function=lambda x: \"%.3f\"%x)\n",
"def SciNot(x):\n",
" xx = \"%.2E\"%x\n",
" base, exp = xx.split(\"E\")\n",
" return \"%s &times; 10<sup>%s</sup>\"%(base, int(exp))\n",
"pt.set_cell_style(cols=[1], format_function=SciNot)\n",
"pt"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<center><table style=\"color: black;border: 1px solid black;\"><tr style=\"color: black;border: 1px solid black;\"><td style=\"color: black;font-weight: bold;background-color: lightgray;\">FloatColumn</td><td style=\"color: black;font-weight: bold;background-color: lightgray;\">SciNotColumn</td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"\">0.032</td><td style=\"\">1.00 &times; 10<sup>10</sup></td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"\">0.234</td><td style=\"\">4.23 &times; 10<sup>-6</sup></td></tr><tr style=\"color: black;border: 1px solid black;\"><td style=\"\">0.556</td><td style=\"\">5.30 &times; 10<sup>-7</sup></td></tr></table></center>"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 9,
"text": [
"<ipywidgets.pretty_table.PrettyTable at 0x4d97910>"
]
}
],
"prompt_number": 9
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Styles\n",
"\n",
"This section shows the insides of how the styling is set up. All of the styling is based on CSS. The major class is ```CellStyle```. Every time you call a function to modify the style of a part of the table, it is modifying the CellStyle of specific cells. \n",
"\n",
"```\n",
"class CellStyle(object):\n",
" \"\"\"\n",
" Styles for cells PrettyTable\n",
" \"\"\"\n",
" \n",
" def __init__(self):\n",
" self.style_elements = {} # dictionary of CSS property -> value\n",
" self.format_function = None\n",
"\n",
" def set(self, key, value):\n",
" self.style_elements[key] = value\n",
"\n",
" def css(self):\n",
" style = \"\"\n",
" for key in self.style_elements:\n",
" style += \"%s: %s;\"%(key, self.style_elements[key])\n",
" return style\n",
"\n",
" def column_format(self, x):\n",
" if self.format_function is None: return str(x)\n",
" else: return self.format_function(x)\n",
"\n",
" def copy(self):\n",
" c = CellStyle()\n",
" c.style_elements = self.style_elements.copy()\n",
" c.format_function = self.format_function\n",
" return c\n",
"```\n",
"This basically stores a dictionary of CSS properties and values, and a function for how to format the data in cells. By using ```set(key, value)```, you can pass any CSS property.The function ```css()``` converts the style elements to CSS that can be used to style tables.\n",
"\n",
"The wrapper class ```TableStyle``` keeps track of separate styles for cells and headings. It also has some preset themes (which I will add to as I need other themes).\n",
"\n",
"```\n",
"class TableStyle(object):\n",
" \"\"\"\n",
" Keep track of styles for cells/headers in PrettyTable\n",
" \"\"\"\n",
" def __init__(self, theme=None):\n",
" self.row_head_style = CellStyle()\n",
" self.col_head_style = CellStyle()\n",
" self.cell_style = CellStyle()\n",
" self.corner_style = CellStyle()\n",
"\n",
" # add themes as needed\n",
" if theme == \"basic\":\n",
" ...\n",
"\n",
" if theme == \"theme1\":\n",
" ...\n",
"\n",
"```\n",
"\n",
"Of course all the properties can be customized, as shown above."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Conclusion\n",
"\n",
"I plan to add themes to this as I go along, and welcome new additions. The main reason I made this class of tables was so I could use them to animate tables in my presentations, which I describe in my next post."
]
}
],
"metadata": {}
}
]
}
@Joseph7e
Copy link

Any examples of final tables?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment