Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

documentation for custom actions #134

Merged
merged 7 commits into from
Nov 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ This website contains pages that overview of the basic and advanced functionalit
source/guide/intent
source/guide/vis
source/guide/export
source/guide/custom
source/guide/default
source/guide/style
source/guide/FAQ
.. source/guide/example
Expand Down
125 changes: 125 additions & 0 deletions doc/source/guide/custom.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
********************************
Defining Custom Actions Globally
********************************

.. note:: You can follow along this tutorial in a Jupyter notebook. [`Github <https://github.com/lux-org/lux-binder/blob/master/tutorial/8-custom-action.ipynb>`_] [`Binder <https://mybinder.org/v2/gh/lux-org/lux-binder/master?urlpath=tree/tutorial/3-widget-vis-export.ipynb>`_]
caitlynachen marked this conversation as resolved.
Show resolved Hide resolved

In this tutorial, we look at the `Happy Planet Index <http://happyplanetindex.org/>`_ dataset, which contains metrics related to well-being for 140 countries around the world. We demonstrate how you can globally define custom actions on the lux API and share them across dataframes.

.. code-block:: python

df = pd.read_csv("https://github.com/lux-org/lux-datasets/blob/master/data/hpi.csv")
lux.config.default_display = "lux" # Set Lux as default display
df

The dataframe initially registers a few default recommendations, such as Correlation, Enhance, Filter, etc.

Registering Custom Actions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Let's define a custom Callable function to generate the recommendations on the dataframe. In this example, we will use G10 to generate a VisList to calculate the percentage change of means Between G10 v.s. non-G10 countries.

.. code-block:: python

caitlynachen marked this conversation as resolved.
Show resolved Hide resolved
def G10_mean_difference(ldf):
intent = [lux.Clause("?",data_type="quantitative"),lux.Clause("G10")]
vlist = VisList(intent,df)

for vis in vlist:
a = vis.data.iloc[0,1]
b = vis.data.iloc[1,1]
vis.score = (b-a)/a
vlist = vlist.topK(15)
return {"action":"G10", "description": "Percentage Change of Means Between G10 v.s. non-G10 countries", "collection": vlist}

In this block, 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 G10.

.. code-block:: python

def is_G10_hpi_dataset(df):
try:
return all(df.columns == ['HPIRank', 'Country', 'SubRegion', 'AverageLifeExpectancy',
'AverageWellBeing', 'HappyLifeYears', 'Footprint',
'InequalityOfOutcomes', 'InequalityAdjustedLifeExpectancy',
'InequalityAdjustedWellbeing', 'HappyPlanetIndex', 'GDPPerCapita',
'Population', 'G10'])
except:
return False

Here, you can register the provided action globally in lux. The function register_action requires an name (str), action, (optional) display_condition and (optional) additional args for the action as parameters.

.. code-block:: python

lux.register_action("G10", G10_mean_difference, is_G10_hpi_dataset)

We can generate the new custom recomendations by calling the Lux dataframe again.

.. code-block:: python

df

.. image:: https://github.com/lux-org/lux-resources/blob/master/doc_img/custom-1.png?raw=true
:width: 700
:align: center
:alt: Displays default and user-defined actions as a VisList.

Using our new action, we can modify our display to only show countries with that reach a certain threshold of GDP and see how their G10 difference compares.

.. code-block:: python

df[df["GDPPerCapita"]>40000]

.. image:: https://github.com/lux-org/lux-resources/blob/master/doc_img/custom-4.png?raw=true
:width: 700
:align: center
:alt: Displays countries with GDPPerCapita > 40000 to compare G10 results.

Navigating the Action Manager
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To see what actions are defined on the Lux Action Manager, the following lines allow you to navigate lux.actions to see both default and user-defined actions.

.. code-block:: python

lux.actions.__len__()

.. image:: https://github.com/lux-org/lux-resources/blob/master/doc_img/custom-5.png?raw=true
:width: 700
:align: center

.. code-block:: python

lux.actions.__getactions__()

caitlynachen marked this conversation as resolved.
Show resolved Hide resolved
.. image:: https://github.com/lux-org/lux-resources/blob/master/doc_img/custom-6.png?raw=true
:width: 700
:align: center

You can also get a single action attribute by calling this function with the action's name.

.. code-block:: python

lux.actions.__getattr__("G10")

.. image:: https://github.com/lux-org/lux-resources/blob/master/doc_img/custom-2.png?raw=true
:width: 700
:align: center
:alt: Retrieves a single attribute from Lux's Action Manager using its defined name.

Removing Custom Actions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This simple function allows you to remove from Lux's action manager an action with its name. The action will no longer display with the Lux dataframe.

.. code-block:: python

lux.remove_action("G10")
df

.. image:: https://github.com/lux-org/lux-resources/blob/master/doc_img/custom-3.png?raw=true
:width: 700
:align: center
:alt: Demonstrates removing custom action from Lux Action Manager.



52 changes: 52 additions & 0 deletions doc/source/guide/default.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
********************************
How To Use Config Class
********************************

In this tutorial, we look at the functionality of the global Config class.

.. code-block:: python

df = pd.read_csv("https://github.com/lux-org/lux-datasets/blob/master/data/hpi.csv")
df

The dataframe initially registers a few default recommendations, such as Correlation, Enhance, Filter, etc, and defaults to a pandas display.

Registering Custom Actions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably beyond the scope of the PR, but what do you think about making default_display a boolean so that only pandas and lux could be selected (0 and 1 respectively). This removes user error from misspelling "lux" or "pandas" (albeit the possibility of that happening is minuscule). You can maybe make the variable more descriptive -- something like default_display_to_lux. Thoughts? @caitlynachen @dorisjlee

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. This is possibly a good idea.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Let's set the default_display of the global class 'Config' to change the default form of output. In the following block, we set it to 'lux,' therefore the VisList will display first.

.. code-block:: python

lux.config.default_display = "lux" # Set Lux as default display
df

.. image:: https://github.com/lux-org/lux-resources/blob/master/doc_img/display-1.png?raw=true
:width: 700
:align: center
:alt: Retrieves a single attribute from Lux's Action Manager using its defined id.

We can set the default_display back to 'pandas,' which would allow for the dataframe object to display first. You can still toggle to Lux/Pandas respectively using the 'Toggle' button.

.. code-block:: python

lux.config.default_display = "pandas" # Set Pandas as default display
df

.. image:: https://github.com/lux-org/lux-resources/blob/master/doc_img/display-2.png?raw=true
:width: 700
:align: center
:alt: Retrieves a single attribute from Lux's Action Manager using its defined id.

If you try to set the default_display to anything other than 'lux' or 'pandas,' a warning will be shown, and the display will default to the previous setting.

.. code-block:: python

lux.config.default_display = "notpandas" # Throw an warning
df

.. image:: https://github.com/lux-org/lux-resources/blob/master/doc_img/display-3.png?raw=true
:width: 700
:align: center
:alt: Retrieves a single attribute from Lux's Action Manager using its defined id.

2 changes: 1 addition & 1 deletion doc/source/guide/export.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Exporting Vis From Widget
********************************

.. note:: You can follow along this tutorial in a Jupyter notebook. [`Github <https://github.com/lux-org/lux-binder/blob/master/tutorial/tutorial/3-widget-vis-export.ipynb>`_] [`Binder <https://mybinder.org/v2/gh/lux-org/lux-binder/master?urlpath=tree/tutorial/3-widget-vis-export.ipynb>`_]
.. note:: You can follow along this tutorial in a Jupyter notebook. [`Github <https://github.com/lux-org/lux-binder/blob/master/tutorial/3-widget-vis-export.ipynb>`_] [`Binder <https://mybinder.org/v2/gh/lux-org/lux-binder/master?urlpath=tree/tutorial/3-widget-vis-export.ipynb>`_]

In this tutorial, we look at the `Happy Planet Index <http://happyplanetindex.org/>`_ dataset, which contains metrics related to well-being for 140 countries around the world. We demonstrate how you can select visualizations of interest and export them for further analysis.

Expand Down
2 changes: 1 addition & 1 deletion doc/source/guide/intent.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Specifying Intent in Lux
********************************

.. note:: You can follow along this tutorial in a Jupyter notebook. [`Github <https://github.com/lux-org/lux-binder/blob/master/tutorial/tutorial/1-specifying-intent.ipynb>`_] [`Binder <https://mybinder.org/v2/gh/lux-org/lux-binder/master?urlpath=tree/tutorial/1-specifying-intent.ipynb>`_]
.. note:: You can follow along this tutorial in a Jupyter notebook. [`Github <https://github.com/lux-org/lux-binder/blob/master/tutorial/1-specifying-intent.ipynb>`_] [`Binder <https://mybinder.org/v2/gh/lux-org/lux-binder/master?urlpath=tree/tutorial/1-specifying-intent.ipynb>`_]

Lux provides a flexible language for communicating your analysis intent to the system, so that Lux can provide better and more relevant recommendations to you. In this tutorial, we will see different ways of specifying the intent, including the attributes and values that you are interested or not interested in, enumeration specifiers, as well as any constraints on the visualization encoding.

Expand Down
2 changes: 1 addition & 1 deletion doc/source/guide/style.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Styling Custom Plot Settings
********************************

.. note:: You can follow along this tutorial in a Jupyter notebook. [`Github <https://github.com/lux-org/lux-binder/blob/master/tutorial/tutorial/4-chart-settings.ipynb>`_] [`Binder <https://mybinder.org/v2/gh/lux-org/lux-binder/master?urlpath=tree/tutorial/4-chart-settings.ipynb>`_]
.. note:: You can follow along this tutorial in a Jupyter notebook. [`Github <https://github.com/lux-org/lux-binder/blob/master/tutorial/4-chart-settings.ipynb>`_] [`Binder <https://mybinder.org/v2/gh/lux-org/lux-binder/master?urlpath=tree/tutorial/4-chart-settings.ipynb>`_]

In the last tutorial, we saw how :code:`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 :code:`plot_config` property of the dataframe.

Expand Down
2 changes: 1 addition & 1 deletion doc/source/guide/vis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Constructing Vis and VisList
********************************

.. note:: You can follow along this tutorial in a Jupyter notebook. [`Github <https://github.com/lux-org/lux-binder/blob/master/tutorial/tutorial/2-constructing-vis-and-vislist.ipynb>`_] [`Binder <https://mybinder.org/v2/gh/lux-org/lux-binder/master?urlpath=tree/tutorial/2-constructing-vis-and-vislist.ipynb>`_]
.. note:: You can follow along this tutorial in a Jupyter notebook. [`Github <https://github.com/lux-org/lux-binder/blob/master/tutorial/2-constructing-vis-and-vislist.ipynb>`_] [`Binder <https://mybinder.org/v2/gh/lux-org/lux-binder/master?urlpath=tree/tutorial/2-constructing-vis-and-vislist.ipynb>`_]

In the earlier tutorials, we have seen how Lux recommends visualizations automatically to the user. Often, the user might have a particular visualizations in mind that they want to specify. In this case, users can quickly define their own visualizations using Lux and visualize their data on-demand.
In this tutorial, we will introduce how to create a visualization via the Vis object and a collection of visualization via the `VisList` object.
Expand Down
2 changes: 0 additions & 2 deletions lux/_config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ def register_action(
args: Any
any additional arguments the function may require
"""
name = name.lower()
if action:
is_callable(action)

Expand All @@ -124,7 +123,6 @@ def remove_action(name: str = "") -> None:
name : str
the name of the action to remove
"""
name = name.lower()
if name not in _registered_actions:
raise ValueError(f"Option '{name}' has not been registered")

Expand Down
8 changes: 4 additions & 4 deletions lux/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,11 +505,11 @@ def maintain_recs(self):
lux.register_action("occurrence", univariate, no_vis, "nominal")
lux.register_action("temporal", univariate, no_vis, "temporal")

lux.register_action("enhance", enhance, one_current_vis)
lux.register_action("filter", filter, one_current_vis)
lux.register_action("generalize", generalize, one_current_vis)
lux.register_action("Enhance", enhance, one_current_vis)
lux.register_action("Filter", filter, one_current_vis)
lux.register_action("Generalize", generalize, one_current_vis)

lux.register_action("custom", custom, multiple_current_vis)
lux.register_action("Custom", custom, multiple_current_vis)

# generate vis from globally registered actions and append to dataframe
custom_action_collection = custom_actions(rec_df)
Expand Down