{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "In this tutorial, we will look at how you can register custom recommendation actions (i.e. tabs of recommendations) to display on the Lux widget. The custom actions can be globally defined and used across different dataframes. We look at the [Happy Planet Index](http://happyplanetindex.org/) dataset, which contains metrics related to well-being for 140 countries around the world. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import lux\n", "\n", "df = pd.read_csv(\"https://raw.githubusercontent.com/lux-org/lux-datasets/master/data/hpi.csv\")\n", "df[\"G10\"] = df[\"Country\"].isin([\"Belgium\",\"Canada\",\"France\",\"Germany\",\"Italy\",\"Japan\",\"Netherlands\",\"United Kingdom\",\"Switzerland\",\"Sweden\",\"United States\"])\n", "lux.config.default_display = \"lux\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As we can see, Lux registers a set of default recommendations to display to users, such as Correlation, Distribution, etc." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Registering Custom Actions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's define a custom function to generate the recommendations on the dataframe. In this example, we register a custom action that showcases numerical measures that differs significantly across G10 and non-G10 countries. [G10 countries](https://en.wikipedia.org/wiki/Group_of_Ten_(economics)) are composed of the ten most industrialized countries in the world, so comparing G10 and non-G10 countries allows us to understand how industrialized and non-industrialized economies differs based on the measures present in the dataframe. \n", "\n", "Here, we first generate a VisList that looks at how various quantitative attributes breakdown between G10 and non-G10 countries. Then, we score and rank these visualization by calculating the percentage difference in means across G10 v.s. non-G10 countries." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from lux.vis.VisList import VisList" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Create a VisList containing G10 with respect to all possible quantitative columns in the dataframe\n", "intent = [lux.Clause(\"?\",data_type=\"quantitative\"),lux.Clause(\"G10\")]\n", "vlist = VisList(intent,df)\n", "\n", "for vis in vlist:\n", " # Percentage Change Between G10 v.s. non-G10 countries\n", " a = vis.data.iloc[0,1]\n", " b = vis.data.iloc[1,1]\n", " vis.score = (b-a)/a\n", "vlist.sort()\n", "vlist.showK()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To define a custom action, we simply wrap our earlier VisList example into a function. We can even use short texts and emojis as the title to display on the tabs for the custom recommendation." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def G10_mean_difference(ldf):\n", " # Define a VisList of quantitative distribution between G10 and non-G10 countries\n", " intent = [lux.Clause(\"?\",data_type=\"quantitative\"),lux.Clause(\"G10\")]\n", " vlist = VisList(intent,ldf)\n", "\n", " # Score each Vis based on the how different G10 and non-G10 bars are\n", " for vis in vlist:\n", " a = vis.data.iloc[0,1]\n", " b = vis.data.iloc[1,1]\n", " vis.score = (b-a)/a\n", " vlist.sort()\n", " vlist.showK()\n", " return {\"action\":\"Compare 🏭🏦🌎\", \n", " \"description\": \"Percentage Change of Means Between G10 v.s. non-G10 countries\",\n", " \"collection\": vlist}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the code below, we define a display condition function to determine whether or not we want to generate recommendations for the custom action. In this example, we simply check if we are using the HPI dataset to generate recommendations for the `Compare industrialized` action." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def is_G10_hpi_dataset(df):\n", " try: \n", " return all(df.columns == ['HPIRank', 'Country', 'SubRegion', 'AverageLifeExpectancy',\n", " 'AverageWellBeing', 'HappyLifeYears', 'Footprint',\n", " 'InequalityOfOutcomes', 'InequalityAdjustedLifeExpectancy',\n", " 'InequalityAdjustedWellbeing', 'HappyPlanetIndex', 'GDPPerCapita',\n", " 'Population', 'G10'])\n", " except: \n", " return False" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To register the `Compare industrialized` action in Lux, we apply the `register_action` function, which takes a name and action as inputs, as well as a display condition and additional arguments as optional parameters." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lux.config.register_action(\"Compare industrialized\", G10_mean_difference, is_G10_hpi_dataset)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After registering the action, the custom action is automatically generated when we display the Lux dataframe again.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As expected, we see that G10 and non-G10 countries differs significantly in terms of their GDPPerCapita, but also in terms of their carbon footprint (Footprint) and number of expected happy year an average citizen can expect to live within a country (HappyLifeYears).\n", "\n", "Since the registered action is globally defined, the G10 action is displayed whenever the display condition is satisfied (i.e. if the data schema matches that of the HPI dataset). For example, we might want to isolate the GDPPerCapita factor and only examine countries with high GDP. We can filter to only countries with GDPPerCapita over 40k and see the difference across the various quantitative attributes for these countries. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df[df[\"GDPPerCapita\"]>40000]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As we can see, there is a less of a distinction between G10 and non-G10 countries across the measures when we only filter to only high GDP countries." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Navigating the Action Manager" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can inspect a list of actions that are currently registered in the Lux Action Manager. The following code displays both default and user-defined actions." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lux.config.actions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also get a single action attribute by calling this function with the action's name." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lux.config.actions.get(\"Compare industrialized\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Removing Custom Actions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's say that we are no longer interested in looking at the `Compare industrialized` action, the `remove_action` function allows you to remove from Lux's action manager an action with its id. The action will no longer display with the Lux dataframe." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lux.config.remove_action(\"Compare industrialized\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After removing the action, when we print the dataframe again, the `Compare industrialized` action is no longer displayed.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df" ] } ], "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.9.2" } }, "nbformat": 4, "nbformat_minor": 4 }