{ "cells": [ { "cell_type": "markdown", "id": "5f34671d-f41e-4c8a-ba33-22807b3069ba", "metadata": {}, "source": [ "# Layer Labels (Annotations) on Waterfall Plot" ] }, { "cell_type": "code", "execution_count": 1, "id": "e0f29545-fd87-4343-b5e9-e0a89fc8674a", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
\n", " \n", " " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from lets_plot import *\n", "from lets_plot.bistro import *\n", "LetsPlot.setup_html()" ] }, { "cell_type": "code", "execution_count": 2, "id": "f2323c7a-5f78-4e6d-974d-da7721d9ddb8", "metadata": {}, "outputs": [], "source": [ "data = {\n", " 'stage': [\"A\", \"B\", \"C\", \"D\", \"E\", \"F\"],\n", " 'count': [598, -264, 156, -4, 330, -85],\n", " 'pct': [100, 44.14, 46.71, 1.81, 67.9, 10.41],\n", "}" ] }, { "cell_type": "markdown", "id": "cf46f8de-f5fb-45ad-a539-58c91d2081b6", "metadata": {}, "source": [ "#### Default Labels" ] }, { "cell_type": "code", "execution_count": 3, "id": "ecf8821c-5672-4f88-9436-9b42ec55922f", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "waterfall_plot(data, 'stage', 'count')" ] }, { "cell_type": "markdown", "id": "d2c0f3fe-50e5-469d-9ed3-dea4acd236e1", "metadata": {}, "source": [ "#### Separate Labels for 'Relative' and 'Absolute' Bars\n", "\n", "The `waterfall_plot()` function now supports two additional parameters, `relative_labels` and `absolute_labels`, which provide separate control over labeling for relative and absolute bars." ] }, { "cell_type": "code", "execution_count": 4, "id": "62fb1c09-5949-4e63-ac49-a36c7b9e78ab", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "waterfall_plot(\n", " data, 'stage', 'count',\n", " relative_labels=layer_labels().line('@pct%').format('@pct', '.0f'),\n", " absolute_labels=layer_labels().line('$@..label..').size(20),\n", ")" ] }, { "cell_type": "markdown", "id": "95160e1e-74c8-4699-a11c-26fe292c23e4", "metadata": {}, "source": [ "#### Multiline Labels\n", "These new parameters also support multiline label configuration." ] }, { "cell_type": "code", "execution_count": 5, "id": "776f78ae-714b-45d4-b105-75f8c66ddfd6", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "waterfall_plot(\n", " data, 'stage', 'count',\n", " relative_labels=layer_labels()\n", " .line('@count') \n", " .line('@pct%')\n", " .format('@pct', '.0f'),\n", " absolute_labels=layer_labels().line('$@..label..').size(20),\n", ")" ] }, { "cell_type": "markdown", "id": "c6730cd1-8ff1-443e-8e21-c307022973e9", "metadata": {}, "source": [ "#### `label_format` parameter and `layer_labels().format()`\n", "By default, labels are generated from the `..label..` data column. The `label_format` parameter specifies the display format for this column and is convenient if you are *not using* `relative_labels` or `absolute_labels`.\n", "\n", "If you're using `relative_labels` or `absolute_labels`, it's recommended to use the `layer_labels().format()` method instead — it allows you to define formatting for each label line individually.\n", "\n", "If needed, you can also override the format of `..label..` explicitly using:\n", "```\n", "layer_labels().line(\"@..label..\").format(\"@..label..\", \".0f\")\n", "```" ] }, { "cell_type": "code", "execution_count": 6, "id": "ce43abf3-2f29-4364-b638-66b895b4c6f8", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "waterfall_plot(\n", " data, 'stage', 'count',\n", " label_format='.1f',\n", " relative_labels=layer_labels()\n", " .line('@..label..')\n", " .line('@count')\n", " .line('@pct%')\n", " .format('@pct', '.0f'),\n", " absolute_labels=layer_labels().line('$@..label..')\n", ")" ] }, { "cell_type": "markdown", "id": "09b7a6c1-4789-4260-9489-75066f85e9a9", "metadata": {}, "source": [ "#### Hiding Labels\n", "The new parameters allow you to hide labels for relative and absolute bars independently." ] }, { "cell_type": "code", "execution_count": 7, "id": "b8df7d11-4c06-4b2e-953a-df9545e4fab8", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "waterfall_plot(\n", " data, 'stage', 'count',\n", " relative_labels='none',\n", " absolute_labels=layer_labels().line('$@..label..').size(20),\n", ")" ] }, { "cell_type": "markdown", "id": "d057073a-e18a-4423-b2a4-40bc41c8636f", "metadata": {}, "source": [ "#### Inheriting the Geometry Color in Labels" ] }, { "cell_type": "code", "execution_count": 8, "id": "f618eb8f-818b-46f7-b085-213a1fb3a73b", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "waterfall_plot(\n", " data, 'stage', 'count',\n", " color='flow_type', # <--- Apply the 'flow type' color palette the boxes (borders). \n", " size=2,\n", " alpha=0.1,\n", " relative_labels=layer_labels()\n", " .line('@..label..')\n", " .line('@count')\n", " .line('@pct%')\n", " .format('@pct', '.0f')\n", " .inherit_color(), # <--- Let text in the 'relative boxes' to inherit the box color.\n", " absolute_labels=layer_labels()\n", " .line('$@..label..')\n", " .size(20),\n", " label=element_text(color='gray30') # <--- Set gray text color to all the labels except the 'relative' (because.. see above)\n", ")" ] }, { "cell_type": "markdown", "id": "8fc0621b-470a-4fe1-94a3-3dbdba55d36b", "metadata": {}, "source": [ "Another, easier way in most cases to inherit the geometry color in text labels is to use the `'inherit'` value in the `label` parameter. \n", "\n", "This affects text in both 'relative' and 'absolute' bars:" ] }, { "cell_type": "code", "execution_count": 9, "id": "c7f41b75-6048-4ac9-96ca-ab696bd78526", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "waterfall_plot(data, 'stage', 'count',\n", " color='flow_type', # <--- Apply the 'flow type' color palette the boxes (borders). \n", " size=2,\n", " alpha=0.1,\n", " label=element_text(color='inherit') # <--- Use 'inherit' color for labels. \n", ")" ] }, { "cell_type": "markdown", "id": "04a42cf4-c8c9-4e80-ab1a-1b93a9aeb821", "metadata": {}, "source": [ "#### When Label doesn't Fit in its Box\n", "- If a label does not fit vertically inside a bar, it is automatically positioned above or below the bar.\n", "- If a label does not fit horizontally, it is rendered with a background to improve readability.\n", "- The text color is automatically adjusted based on the background color to ensure sufficient contrast." ] }, { "cell_type": "code", "execution_count": 10, "id": "a6e15271-0216-4eab-8ed0-6c02db5d41b9", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gggrid([\n", " waterfall_plot(data, 'stage', 'count', width=.2),\n", " waterfall_plot(data, 'stage', 'count', width=.2) + flavor_darcula() \n", "]) " ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.9.23" } }, "nbformat": 4, "nbformat_minor": 5 }