{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Styling Custom Plot Settings " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import lux" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df = pd.read_csv(\"../data/car.csv\")\n", "df[\"Year\"] = pd.to_datetime(df[\"Year\"], format='%Y') # change pandas dtype for the column \"Year\" to datetype\n", "lux.config.default_display=\"lux\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the last tutorial, we saw how `Vis` objects could be exported into visualization code for further editing. What if we want to change the chart settings for *all* the visualizations displayed in the widget. In Lux, we can change the chart settings and aesthetics by inputting custom plot settings the `plotting_style` property of the dataframe." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Example #1 : Changing Color and Title of all charts" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here, we've loaded in the [Cars dataset](http://lib.stat.cmu.edu/datasets/) and the visualizations recommended in the widget are in its default settings." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By default, visualizations in Lux are rendered using the [Altair](https://altair-viz.github.io/index.html) library.\n", "To change the plot configuration in Altair, we need to specify a function that takes an [AltairChart](https://altair-viz.github.io/user_guide/generated/toplevel/altair.Chart.html?highlight=chart) as input, performs some chart configurations in Altair, and returns the chart object as an output.\n", "\n", "Let's say that we want to change all the graphical marks of the charts to green and add a custom title. We can define this `change_color_add_title` function, which configures the chart's mark as green and adds a custom title to the chart." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def change_color_add_title(chart):\n", " chart = chart.configure_mark(color=\"green\") # change mark color to green\n", " chart.title = \"Custom Title\" # add title to chart\n", " return chart" ] }, { "cell_type": "markdown", "metadata": {}, "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lux.config.plotting_style = change_color_add_title" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Matplotlib also supports plot configurations to be applied on top of the generated graphs. To set a default plot configuration, first write a function that can take in a `fig` and `ax` and returns a `fig` and `ax`. \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lux.config.plotting_backend = \"matplotlib\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`fig` handles figure width and other plot size attributes. `ax` supports changing the chart title and other plot labels and configurations. For example:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def change_width_add_title(fig, ax):\n", " fig.set_figwidth(7)\n", " ax.set_title(\"Custom Title\")\n", " return fig, ax" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lux.config.plotting_style = change_width_add_title" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Moreover, we can set the color and other figure styles using the rcParams attribute of pyplot." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import matplotlib\n", "\n", "plt.rcParams['axes.prop_cycle'] = matplotlib.cycler(color='g')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We now see that the displayed visualizations adopt these new imported settings once we force lux to recompute its recommendations. \n", "\n", "*Note: currently, if we want these plot configurations to show up on a DataFrame already loaded, we must also add `df.expire_recs()`*" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.expire_recs()\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we click on the visualization for `Displacement` v.s. `Weight` and export it. We see that the exported chart now contains code with these additional plot settings at the every end." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Before running this cell, click on Displacement v.s. Weight vis and export it.\n", "vis = df.exported[0]\n", "print (vis.to_altair())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import altair as alt\n", "\n", "chart = alt.Chart(df).mark_circle().encode(\n", " x=alt.X('Weight',scale=alt.Scale(domain=(1613, 5140)),type='quantitative'),\n", " y=alt.Y('Displacement',scale=alt.Scale(domain=(68.0, 455.0)),type='quantitative')\n", ")\n", "chart = chart.configure_mark(tooltip=alt.TooltipContent('encoding')) # Setting tooltip as non-null\n", "chart = chart.interactive() # Enable Zooming and Panning\n", "chart = chart.configure_title(fontWeight=500,fontSize=13,font='Helvetica Neue')\n", "chart = chart.configure_axis(titleFontWeight=500,titleFontSize=11,titleFont='Helvetica Neue',\n", "\t\t\tlabelFontWeight=400,labelFontSize=8,labelFont='Helvetica Neue',labelColor='#505050')\n", "chart = chart.configure_legend(titleFontWeight=500,titleFontSize=10,titleFont='Helvetica Neue',\n", "\t\t\tlabelFontWeight=400,labelFontSize=8,labelFont='Helvetica Neue')\n", "chart = chart.properties(width=160,height=150)\n", "chart = chart.configure_mark(color=\"green\") # change mark color to green\n", "chart.title = \"Custom Title\" # add title to chart\n", "chart" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also export these Matplotlib charts with the plotting style." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Before running this cell, click on Displacement v.s. Weight vis and export it.\n", "vis = df.exported[0]\n", "print (vis.to_matplotlib())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "plt.rcParams.update(\n", " {\n", " \"axes.titlesize\": 20,\n", " \"axes.titleweight\": \"bold\",\n", " \"axes.labelweight\": \"bold\",\n", " \"axes.labelsize\": 16,\n", " \"legend.fontsize\": 14,\n", " \"legend.title_fontsize\": 15,\n", " \"xtick.labelsize\": 13,\n", " \"ytick.labelsize\": 13,\n", " }\n", " )\n", "import numpy as np\n", "from math import nan\n", "from matplotlib.cm import ScalarMappable\n", "fig, ax = plt.subplots(figsize=(4.5, 4))\n", "x_pts = df['Displacement']\n", "y_pts = df['Weight']\n", "ax.scatter(x_pts, y_pts, alpha=0.5)\n", "ax.set_xlabel('Displacement', fontsize='15')\n", "ax.set_ylabel('Weight', fontsize='15')\n", "fig.set_figwidth(7)\n", "ax.set_title(\"Custom Title\")\n", "fig" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Example #2: Changing Selected Chart Setting" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we look at an example of customizing the chart setting for only selected sets of visualizations. \n", "\n", "Here, we load in the [Olympics dataset](https://www.kaggle.com/heesoo37/120-years-of-olympic-history-athletes-and-results) and see that the recommended visualization is cluttered with many datapoints." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "url = 'https://github.com/lux-org/lux-datasets/blob/master/data/olympic.csv?raw=true'\n", "df = pd.read_csv(url)\n", "df[\"Year\"] = pd.to_datetime(df[\"Year\"], format='%Y') # change pandas dtype for the column \"Year\" to datetype\n", "lux.config.default_display=\"lux\"\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We want to decrease the opacity of scatterplots, but keep the opacity for the other types of visualization as default." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def changeOpacityScatterOnly(chart):\n", " chart = chart.configure_circle(opacity=0.1) # lower opacity if circle\n", " return chart" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lux.config.plotting_style = changeOpacityScatterOnly\n", "df.expire_recs()\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can modify the scatterplot setting, without changing the settings for the other chart types." ] } ], "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.8.5" } }, "nbformat": 4, "nbformat_minor": 4 }