{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Interactive Tables and their API\n", "\n", "The table UI allows column drag/drop, hide, sorting, formatting, searching, selecting/export as CSV. This makes it easy to paste into a spreadsheet like Excel.\n", "\n", "There is a menu in the top-left for the whole table, and each column has a menu that appears on hover.\n", "\n", "There are also keyboard commands: digits change the precision of all columns, shift-digit changes the precision of the current column. Arrow keys navigate, and the page up/down keys work too." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "new TableDisplay( new CSV().read(\"../resources/data/interest-rates.csv\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Formatting and Alignment" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import com.twosigma.beakerx.table.*\n", "import com.twosigma.beakerx.table.format.TableDisplayStringFormat\n", "\n", "display = new TableDisplay(new CSV().read(\"../resources/data/interest-rates.csv\"))\n", "//show all time columns in days\n", "display.setStringFormatForTimes(TimeUnit.DAYS)\n", "//min 4, max 6 decimal places for all doubles\n", "display.setStringFormatForType(ColumnType.Double, TableDisplayStringFormat.getDecimalFormat(4,6))\n", "//setting for a column takes precidence over the type\n", "display.setStringFormatForColumn(\"m3\", TableDisplayStringFormat.getDecimalFormat(0, 0))\n", "//set the alignment\n", "display.setAlignmentProviderForType(ColumnType.Double, TableDisplayAlignmentProvider.RIGHT_ALIGNMENT)\n", "display.setAlignmentProviderForColumn('m3', TableDisplayAlignmentProvider.CENTER_ALIGNMENT)\n", "\n", "//using a closure\n", "display.setStringFormatForColumn(\"y3\") { value, row, col, tableDisplay ->\n", " if(value < 8) {\n", " \":(\"\n", " } else {\n", " \":)\"\n", " } \n", "}\n", "\n", "display" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This changes the format of the table above in the previous output cell. It's updated because the object is synchronized between the kernel and the client." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "display.setStringFormatForTimes(TimeUnit.HOURS)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Bar Charts Renderer" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import com.twosigma.beakerx.table.*\n", "import com.twosigma.beakerx.table.renderer.TableDisplayCellRenderer\n", "\n", "def display2 = new TableDisplay(new CSV().read(\"../resources/data/interest-rates.csv\"))\n", "//right now, the only renderer option is for data bars\n", "display2.setRendererForType(ColumnType.Double, TableDisplayCellRenderer.getDataBarsRenderer())\n", "//use the false parameter to hide the String value\n", "display2.setRendererForColumn(\"y10\", TableDisplayCellRenderer.getDataBarsRenderer(false))\n", "display2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Column Visibility and Placement" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import com.twosigma.beakerx.table.*\n", "import com.twosigma.beakerx.fileloader.CSV\n", "import com.twosigma.beakerx.table.format.TableDisplayStringFormat\n", "\n", "def display3 = new TableDisplay(new CSV().read(\"../resources/data/interest-rates.csv\"))\n", "display3.setStringFormatForType(ColumnType.Double, TableDisplayStringFormat.getDecimalFormat(9,9))\n", "//freeze a column\n", "display3.setColumnFrozen(\"y1\", true)\n", "//freeze a column to the right\n", "display3.setColumnFrozenRight(\"y10\", true)\n", "//hide a column\n", "display3.setColumnVisible(\"y30\", false)\n", "\n", "//explicitly set column order/visiblity\n", "display3.setColumnOrder([\"m3\", \"y1\", \"y5\", \"time\", \"y2\"]) //Columns in the list will be shown in the provided order. Columns not in the list will be hidden.\n", "display3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Heatmaps" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import com.twosigma.beakerx.table.*\n", "import com.twosigma.beakerx.table.highlight.TableDisplayCellHighlighter\n", "\n", "def display4 = new TableDisplay(new CSV().read(\"../resources/data/interest-rates.csv\"))\n", "display4.addCellHighlighter(TableDisplayCellHighlighter.getHeatmapHighlighter(\"m3\", TableDisplayCellHighlighter.FULL_ROW))\n", "\n", "//the following two overloads should also be supported\n", "//set the min and max used for calculating the color\n", "//display4.addCellHighlighter(TableDisplayCellHighlighter.getHeatmapHighlighter(\"y1\", TableDisplayCellHighlighter.FULL_ROW, 0, 5))\n", "//set the colors used for the min and max\n", "//display4.addCellHighlighter(TableDisplayCellHighlighter.getHeatmapHighlighter(\"m6\", TableDisplayCellHighlighter.SINGLE_COLUMN, null, null, Color.YELLOW, Color.BLUE))\n", "\n", "display4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cell Background Color" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def map = [\n", " [a:1, b:2, c:3],\n", " [a:4, b:5, c:6],\n", " [a:7, b:8, c:5]\n", "]\n", "def display5 = new TableDisplay(map)\n", "display5.addCellHighlighter { row, column, tableDisplay ->\n", " if (column == 2) {\n", " display5.values[row][column] < 5 ? Color.RED : Color.GREEN\n", " }\n", "}\n", "display5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Heatmaps per Column" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import com.twosigma.beakerx.table.*\n", "import com.twosigma.beakerx.table.highlight.*\n", "\n", "display6 = new TableDisplay(new CSV().read(\"../resources/data/interest-rates.csv\"))\n", "display6.addCellHighlighter(TableDisplayCellHighlighter.getHeatmapHighlighter(\"m3\", 0, 8, Color.ORANGE, Color.PINK))\n", "display6.addCellHighlighter(TableDisplayCellHighlighter.getHeatmapHighlighter(\"m6\", TableDisplayCellHighlighter.SINGLE_COLUMN, 6, 8, Color.BLACK, Color.PINK))\n", "\n", "display6.addCellHighlighter(new ThreeColorHeatmapHighlighter(\"y1\", TableDisplayCellHighlighter.SINGLE_COLUMN, 4, 6, 8, new Color(247,106,106), new Color(239,218,82), new Color(100,189,122)))\n", "\n", "display6" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "display6.removeAllCellHighlighters()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Color Unique Entries" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import com.twosigma.beakerx.table.highlight.*\n", "\n", "def table = new TableDisplay([[1,2,3], \n", " [3,4,5], \n", " [6,2,8], \n", " [6,2,8], \n", " [6,2,8], \n", " [6,4,8], \n", " [6,2,8], \n", " [6,2,8], \n", " [6,5,8]], \n", " ['a', 'b', 'c'], \n", " ['double', 'double', 'double'])\n", "table.addCellHighlighter(TableDisplayCellHighlighter.getUniqueEntriesHighlighter(\"b\", TableDisplayCellHighlighter.FULL_ROW))\n", "table" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Font Size, Color, and Vertical Headers" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def mapList5 = [\n", " [firstCol:1, secondCol:2, thirdCol:3],\n", " [firstCol:4, secondCol:5, thirdCol:6],\n", " [firstCol:9, secondCol:8, thirdCol:9]\n", "]\n", "def td4 = new TableDisplay(mapList5)\n", "\n", "//tool tip can be set with a closure\n", "td4.setToolTip { row, col, display ->\n", " \"The value is: \" + display.values[row][col]\n", "}\n", "td4\n", "\n", "//set the font size and color\n", "td4.dataFontSize = 35\n", "td4.headerFontSize = 30\n", "\n", "def colors = [[Color.LIGHT_GRAY, Color.GRAY, Color.RED],\n", " [Color.DARK_GREEN, Color.ORANGE, Color.RED],\n", " [Color.MAGENTA, Color.BLUE, Color.BLACK]]\n", "\n", "td4.setFontColorProvider { row, col, td ->\n", " colors[row][col]\n", "}\n", "\n", "//try different filter options\n", "td4.setRowFilter { row, model ->\n", " //model[row][1] == 8\n", " true\n", " //false\n", " //model[row][0] == model[row][2]\n", "}\n", "\n", "//set vertical headers\n", "//you can also do this in the right-click menu\n", "td4.setHeadersVertical(true)\n", "\n", "td4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Programmable Actions\n", "\n", "Bind a closure or running a cell to the context menu or double click action on the table." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "abc = 0; // test variable\n", "mapList = [\n", " [a:1, b:2, c:3],\n", " [a:4, b:5, c:6],\n", " [a:7, b:8, c:5]\n", "]\n", "OutputCell.HIDDEN" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def display1 = new TableDisplay(mapList)\n", "//set what happens on a double click\n", "display1.setDoubleClickAction { row, col, tableDisplay ->\n", " tableDisplay.values[row][col] = tableDisplay.values[row].sum()\n", "}\n", "\n", "//add a context menu item\n", "display1.addContextMenuItem(\"negate\") { row, col, tableDisplay ->\n", " tableDisplay.values[row][col] = -tableDisplay.values[row][col]\n", "}\n", "\n", "display1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def display2 = new TableDisplay(mapList)\n", "\n", "//run tagged cell on action\n", "display2.addContextMenuItem(\"run print cell\", \"print_cell\");\n", "display2.setDoubleClickAction(\"print_cell\");\n", "\n", "display2" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "print_cell" ] }, "outputs": [], "source": [ "abc++\n", "println abc" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "display4 = new TableDisplay(mapList)\n", "\n", "//run tagged cell on action\n", "display4.addContextMenuItem(\"run tagged_cell cell\", \"tagged_cell\");\n", "display4.setDoubleClickAction(\"tagged_cell\");\n", "\n", "display4" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "tagged_cell" ] }, "outputs": [], "source": [ "def details = display4.details\n", "\n", "if(details != null){\n", " switch(details.actionType){\n", " case 'DOUBLE_CLICK':\n", " print (\"You clicked on the cell [\" + details.row + \", \" + details.col + \"]\")\n", " break;\n", " case 'CONTEXT_MENU_CLICK':\n", " print (\"You selected context menu '\" + details.contextMenuItem + \"' on the cell [\" + details.row + \", \" + details.col + \"]\")\n", " break;\n", " }\n", "}else{\n", " println \"no table tag action performed.\"\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## HTML format\n", "\n", "HTML format allows markup and styling of the cell's content. Interactive JavaScript is not supported however." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "tbl = new TableDisplay([x: 'italic red',\n", " y: 'bold blue',\n", " z: 'multiline strings
work fine too']);\n", "tbl.setStringFormatForColumn(\"Value\", TableDisplayStringFormat.getHTMLFormat())\n", "tbl" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Auto linking of URLs\n", "\n", "The normal string format automatically detects URLs and links them. An underline appears when the mouse hovers over such a string, and when you click it opens in a new window." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "new TableDisplay(['Two Sigma': 'http://twosigma.com', 'BeakerX': 'surrounding text http://BeakerX.com works fine'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Seamless Update" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def mapListToUpdate = [\n", " [a:1, b:2, c:3],\n", " [a:4, b:5, c:6],\n", " [a:7, b:8, c:9]\n", "]\n", "tableToUpdate = new TableDisplay(mapListToUpdate)\n", "\n", "tableToUpdate" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "tableToUpdate.values[0][0] = 99\n", "tableToUpdate.sendModel()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "tableToUpdate.updateCell(2,\"c\",121)\n", "tableToUpdate.sendModel()" ] } ], "metadata": { "anaconda-cloud": {}, "beakerx_kernel_parameters": {}, "celltoolbar": "Tags", "kernelspec": { "display_name": "Groovy", "language": "groovy", "name": "groovy" }, "language_info": { "codemirror_mode": "groovy", "file_extension": ".groovy", "mimetype": "", "name": "Groovy", "nbconverter_exporter": "", "version": "2.4.3" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": false, "sideBar": false, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": false, "toc_window_display": false }, "widgets": { "state": { "f7d30807-6d2d-414d-b604-fcb0ed748612": { "views": [ { "cell_index": 0 }, { "cell_index": 1 } ] } }, "version": "1.2.0" } }, "nbformat": 4, "nbformat_minor": 2 }