{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# ipydatagrid" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from ipydatagrid import DataGrid, TextRenderer, BarRenderer, Expr" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from json import load\n", "import pandas as pd\n", "\n", "with open(\"./cars.json\") as fobj:\n", " data = load(fobj)\n", "df = pd.DataFrame(data[\"data\"]).set_index(\"index\")\n", "df = df[sorted(df.columns)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Custom cell renderers\n", "\n", "Custom cell renderers can be defined for the entire grid or column-wise.\n", "\n", "Two types of cell renderers are currently available: `TextRenderer` and `BarRenderer`.\n", "\n", "Most of the `TextRenderer`/`BarRenderer` attributes (`background_color`, `text_color` etc.) can either be a __value__, a __bqplot scale__ or a __`VegaExpr`__ or __`Expr`__ instance.\n", "\n", "\n", "### Vega expressions\n", "The `VegaExpr` class allows you to define an attribute value as a result of a Vega-expression (see https://vega.github.io/vega/docs/expressions/). _e.g._ `background_color = VegaExpr(\"value < 150 ? 'red' : 'green'\")`.\n", " \n", "You can look at the vega-expression documentation for more information about available constants and functions. In the scope of the expression are also available: `value`: cell value, `x` and `y`: cell position in pixel, `width` and `height` of the cell, `row` and `column`: cell position.\n", "\n", "### Python expressions\n", "If you prefer writing those expressions in Python, we provide an `Expr` class which takes a Python expression as input string or a Python function, and generates the equivalent vega-expression for you using [py2vega](https://github.com/Bloomberg/py2vega)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from bqplot import LinearScale, ColorScale, OrdinalColorScale, OrdinalScale\n", "from py2vega.functions.color import rgb\n", "\n", "\n", "def horsepower_coloring(cell):\n", " if cell.value < 100:\n", " return \"red\"\n", " elif cell.value < 150:\n", " return \"orange\"\n", " else:\n", " return \"green\"\n", "\n", "\n", "def weight_coloring(cell):\n", " scaled_value = 1 if cell.value > 4500 else cell.value / 4500\n", " color_value = scaled_value * 255\n", "\n", " return rgb(color_value, 0, 0)\n", "\n", "\n", "renderers = {\n", " \"Acceleration\": BarRenderer(\n", " horizontal_alignment=\"center\",\n", " bar_color=ColorScale(min=0, max=20, scheme=\"viridis\"),\n", " bar_value=LinearScale(min=0, max=20),\n", " ),\n", " \"Cylinders\": TextRenderer(\n", " background_color=Expr('\"grey\" if cell.row % 2 else default_value')\n", " ),\n", " \"Displacement\": TextRenderer(\n", " text_color=ColorScale(min=97, max=455),\n", " font=Expr(\n", " \"'16px sans-serif' if cell.value > 400 else '12px sans-serif'\"\n", " ),\n", " ),\n", " \"Horsepower\": TextRenderer(\n", " text_color=\"black\", background_color=Expr(horsepower_coloring)\n", " ),\n", " \"Miles_per_Gallon\": TextRenderer(\n", " background_color=Expr('\"grey\" if cell.value is None else default_value')\n", " ),\n", " \"Name\": TextRenderer(\n", " background_color=Expr(\n", " 'rgb(0, 100, 255) if \"chevrolet\" in cell.value or \"ford\" in cell.value else default_value'\n", " )\n", " ),\n", " \"Origin\": TextRenderer(\n", " text_color=\"black\",\n", " background_color=OrdinalColorScale(domain=[\"USA\", \"Japan\", \"Europe\"]),\n", " horizontal_alignment=Expr(\n", " \"'right' if cell.value in ['USA', 'Japan'] else 'left'\"\n", " ),\n", " ),\n", " \"Weight_in_lbs\": TextRenderer(\n", " text_color=\"black\", background_color=Expr(weight_coloring)\n", " ),\n", " \"Year\": TextRenderer(text_color=\"black\", background_color=\"green\"),\n", "}\n", "\n", "datagrid = DataGrid(\n", " df, base_row_size=32, base_column_size=150, renderers=renderers\n", ")\n", "datagrid" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "renderers[\n", " \"Name\"\n", "].background_color.value = '\"green\" if \"pontiac\" in cell.value or \"citroen\" in cell.value else default_value'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "renderers[\"Year\"].background_color = \"yellow\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "datagrid.transform(\n", " [\n", " {\n", " \"type\": \"filter\",\n", " \"operator\": \"=\",\n", " \"columnIndex\": 7,\n", " \"value\": \"Europe\",\n", " },\n", " {\"type\": \"sort\", \"columnIndex\": 3, \"desc\": True},\n", " ]\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "datagrid.revert()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "datagrid.transform(\n", " [\n", " {\"type\": \"filter\", \"operator\": \"=\", \"columnIndex\": 7, \"value\": \"USA\"},\n", " {\"type\": \"filter\", \"operator\": \"<\", \"columnIndex\": 1, \"value\": 13},\n", " {\"type\": \"sort\", \"columnIndex\": 1},\n", " ]\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Perfomance test: A million cells with ipydatagrid" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from random import uniform\n", "\n", "\n", "def create_random_data(n_rows=100, n_columns=100):\n", " data = {\"data\": [], \"schema\": {}}\n", "\n", " data[\"data\"] = [\n", " [uniform(0, 1) for c in range(n_columns)] for r in range(n_rows)\n", " ]\n", " data[\"schema\"][\"fields\"] = [\n", " {\"name\": str(c), type: \"number\"} for c in range(n_columns)\n", " ]\n", "\n", " return data\n", "\n", "\n", "def update_random_data(old_data):\n", " data = {\"data\": [], \"schema\": {}}\n", "\n", " n_columns = len(old_data[\"data\"])\n", " n_rows = len(old_data[\"data\"][0])\n", "\n", " data[\"data\"] = [\n", " [uniform(-0.1, 0.1) + old_data[\"data\"][r][c] for c in range(n_columns)]\n", " for r in range(n_rows)\n", " ]\n", " data[\"schema\"][\"fields\"] = [\n", " {\"name\": str(c), type: \"number\"} for c in range(n_columns)\n", " ]\n", "\n", " return data" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from py2vega.constants import SQRT1_2\n", "\n", "huge_data = create_random_data(1000, 1000)\n", "\n", "\n", "def renderer_function(cell, default_value):\n", " return \"#fc8403\" if cell.value < SQRT1_2 else default_value\n", "\n", "\n", "conditional_expression = Expr(renderer_function)\n", "\n", "default_renderer = TextRenderer(\n", " background_color=conditional_expression, format=\".3f\"\n", ")\n", "\n", "huge_df = pd.DataFrame(huge_data[\"data\"])\n", "\n", "conditional_huge_datagrid = DataGrid(huge_df, default_renderer=default_renderer)\n", "conditional_huge_datagrid" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from ipywidgets import FloatSlider, Dropdown, ColorPicker, HBox, VBox\n", "\n", "operator_dropdown = Dropdown(options=[\"<\", \">\"], value=\"<\")\n", "reference_slider = FloatSlider(value=0.5, min=0, max=1)\n", "output_colorpicker = ColorPicker(value=\"#fc8403\")\n", "\n", "\n", "def on_change(*args, **kwargs):\n", " conditional_expression.value = \"'{color}' if cell.value {operator} {reference} else default_value\".format(\n", " operator=operator_dropdown.value,\n", " reference=reference_slider.value,\n", " color=output_colorpicker.value,\n", " )\n", "\n", "\n", "operator_dropdown.observe(on_change, \"value\")\n", "reference_slider.observe(on_change, \"value\")\n", "output_colorpicker.observe(on_change, \"value\")\n", "\n", "hbox = HBox((operator_dropdown, reference_slider, output_colorpicker))\n", "VBox([conditional_huge_datagrid, hbox])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Bar renderer" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from bqplot import LinearScale, ColorScale\n", "from ipydatagrid import DataGrid, BarRenderer\n", "\n", "linear_scale = LinearScale(min=0, max=1)\n", "color_scale = ColorScale(min=0, max=1)\n", "bar_renderer = BarRenderer(\n", " bar_color=color_scale,\n", " bar_value=linear_scale,\n", " bar_horizontal_alignment=\"center\",\n", " show_text=False,\n", ")\n", "\n", "huge_df2 = pd.DataFrame(create_random_data()[\"data\"])\n", "\n", "huge_datagrid = DataGrid(huge_df2, default_renderer=bar_renderer)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "huge_datagrid" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from ipywidgets import FloatSlider, link\n", "\n", "slider = FloatSlider(\n", " description=\"Scale: \", value=linear_scale.max, min=0, max=1, step=0.01\n", ")\n", "link((color_scale, \"min\"), (slider, \"value\"))\n", "link((linear_scale, \"min\"), (slider, \"value\"))\n", "\n", "slider" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "color_scale.scheme = \"magma\"" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.6" } }, "nbformat": 4, "nbformat_minor": 4 }