Repository: lux-org/lux

Issue:
[Feature Request] Geographic data support for Matplotlib 
# Feature Request Description 
Via #253, we now have support for geographic data types using Vegalite as the backend. We would like to extend support for this feature on [Matplotlib](https://matplotlib.org/) as well. 

For example, running 
```
lux.config.plotting_backend = "vegalite" # default
df = pd.read_csv("https://github.com/covidvis/covid19-vis/blob/master/data/interventionFootprintByState.csv?raw=True",index_col=0)
df
```
yields the following result: 
![Screen Shot 2021-03-17 at 2 14 58 PM](https://user-images.githubusercontent.com/44735047/111540455-681d6600-872c-11eb-9df3-12f8c873068f.png)
When we configure the backend with
```
lux.config.plotting_backend = "matplotlib"
```
the output does not display for a Matplotlib backend. 

## Solution
To resolve for now, we will call upon the `AltairRenderer` and warn users that the Choropleths are rendered via the Altair backend. 

If users indicate enough interest, we will add a mirroring `Choropleth.py` file in `lux/vislib/matplotlib`, which will be called upon by the same `univariate` action when the backend is set to `matplotlib`. 

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/lux-org/lux/pull/322?src=pr&el=h1) Report
> Merging [#322](https://codecov.io/gh/lux-org/lux/pull/322?src=pr&el=desc) (6e33afe) into [master](https://codecov.io/gh/lux-org/lux/commit/2553125fa8bd551b10d85ad67419bcd9b3b0eeab?el=desc) (2553125) will **increase** coverage by `0.02%`.
> The diff coverage is `14.28%`.

> :exclamation: Current head 6e33afe differs from pull request most recent head eecfee0. Consider uploading reports for the commit eecfee0 to get more accurate results
[![Impacted file tree graph](https://codecov.io/gh/lux-org/lux/pull/322/graphs/tree.svg?width=650&height=150&src=pr&token=skTUnFpwwX)](https://codecov.io/gh/lux-org/lux/pull/322?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #322      +/-   ##
==========================================
+ Coverage   80.87%   80.89%   +0.02%     
==========================================
  Files          50       50              
  Lines        3618     3623       +5     
==========================================
+ Hits         2926     2931       +5     
  Misses        692      692              
```


| [Impacted Files](https://codecov.io/gh/lux-org/lux/pull/322?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [lux/vislib/altair/Choropleth.py](https://codecov.io/gh/lux-org/lux/pull/322/diff?src=pr&el=tree#diff-bHV4L3Zpc2xpYi9hbHRhaXIvQ2hvcm9wbGV0aC5weQ==) | `94.20% <0.00%> (ø)` | |
| [lux/vislib/matplotlib/MatplotlibRenderer.py](https://codecov.io/gh/lux-org/lux/pull/322/diff?src=pr&el=tree#diff-bHV4L3Zpc2xpYi9tYXRwbG90bGliL01hdHBsb3RsaWJSZW5kZXJlci5weQ==) | `81.53% <16.66%> (-5.13%)` | :arrow_down: |
| [lux/vislib/matplotlib/ScatterChart.py](https://codecov.io/gh/lux-org/lux/pull/322/diff?src=pr&el=tree#diff-bHV4L3Zpc2xpYi9tYXRwbG90bGliL1NjYXR0ZXJDaGFydC5weQ==) | `76.47% <0.00%> (+1.17%)` | :arrow_up: |
| [lux/vislib/matplotlib/Heatmap.py](https://codecov.io/gh/lux-org/lux/pull/322/diff?src=pr&el=tree#diff-bHV4L3Zpc2xpYi9tYXRwbG90bGliL0hlYXRtYXAucHk=) | `98.33% <0.00%> (+1.66%)` | :arrow_up: |
| [lux/vislib/altair/ScatterChart.py](https://codecov.io/gh/lux-org/lux/pull/322/diff?src=pr&el=tree#diff-bHV4L3Zpc2xpYi9hbHRhaXIvU2NhdHRlckNoYXJ0LnB5) | `96.96% <0.00%> (+3.03%)` | :arrow_up: |
| [lux/vislib/altair/Heatmap.py](https://codecov.io/gh/lux-org/lux/pull/322/diff?src=pr&el=tree#diff-bHV4L3Zpc2xpYi9hbHRhaXIvSGVhdG1hcC5weQ==) | `96.55% <0.00%> (+3.44%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/lux-org/lux/pull/322?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/lux-org/lux/pull/322?src=pr&el=footer). Last update [2553125...eecfee0](https://codecov.io/gh/lux-org/lux/pull/322?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/README.md b/README.md
index 103f670..a8f7e56 100644
--- a/README.md
+++ b/README.md
@@ -131,15 +131,16 @@ VisList(["Region=?","AverageCost"],df)
 
 To find out more about other features in Lux, see the complete documentation on [ReadTheDocs](https://lux-api.readthedocs.io/).
 
-# Installation 
+# Installation & Setup
 
-To get started, Lux can be installed through [PyPI](https://pypi.org/project/lux-api/). 
+To get started, please follow both the installation and setup instructions in your command line.
+`lux-api` can be installed through [PyPI](https://pypi.org/project/lux-api/). 
 
 ```bash
 pip install lux-api
 ```
 
-If you use [conda](https://docs.conda.io/en/latest/), you can install Lux via:
+If you use [conda](https://docs.conda.io/en/latest/), you can install `lux-api` via:
 
 ```bash
 conda install -c conda-forge lux-api
@@ -147,9 +148,9 @@ conda install -c conda-forge lux-api
 
 Both the PyPI and conda installation include includes the Lux Jupyter widget frontend, [lux-widget](https://pypi.org/project/lux-widget/). 
 
-## Setup in Jupyter Notebook, VSCode
+## Setup in Jupyter Notebook, VSCode, JupyterHub
 
-To use Lux in [Jupyter notebook](https://github.com/jupyter/notebook) or [VSCode](https://code.visualstudio.com/docs/python/jupyter-support), activate the notebook extension:
+To use Lux with any Jupyter notebook-based frontends (e.g., [Jupyter notebook](https://github.com/jupyter/notebook), [JupyterHub](https://github.com/jupyterhub/jupyterhub), or [VSCode](https://code.visualstudio.com/docs/python/jupyter-support)), activate the notebook extension:
 
 ```bash
 jupyter nbextension install --py luxwidget
@@ -157,6 +158,7 @@ jupyter nbextension enable --py luxwidget
 ```
 
 If the installation happens correctly, you should see two `- Validating: OK` after executing the two lines above.
+Note that you may have to restart the Jupyter Notebook server to ensure that the widget is displaying correctly.
 
 ## Setup in Jupyter Lab
 
@@ -166,7 +168,7 @@ To use Lux in [Jupyter Lab](https://github.com/jupyterlab/jupyterlab), activate
 jupyter labextension install @jupyter-widgets/jupyterlab-manager
 jupyter labextension install luxwidget
 ```
-Lux is only compatible with Jupyter Lab version 2.2.9 and below. Support for the recent [JupyterLab 3](https://blog.jupyter.org/jupyterlab-3-0-is-out-4f58385e25bb) will come soon. Note that JupyterLab and VSCode is supported only for lux-widget version >=0.1.2, if you have an earlier version, please upgrade to the latest version of [lux-widget](https://pypi.org/project/lux-widget/). Lux currently only works with the Chrome browser. 
+Lux is only compatible with Jupyter Lab version 2.2.9 and below. Support for the recent [JupyterLab 3](https://blog.jupyter.org/jupyterlab-3-0-is-out-4f58385e25bb) will come soon. Note that JupyterLab and VSCode is supported only for lux-widget version >=0.1.2, if you have an earlier version, please upgrade to the latest version of [lux-widget](https://pypi.org/project/lux-widget/). Lux has only been tested with the Chrome browser. 
 
 If you encounter issues with the installation, please refer to [this page](https://lux-api.readthedocs.io/en/latest/source/guide/FAQ.html#troubleshooting-tips) to troubleshoot the installation. Follow [these instructions](https://lux-api.readthedocs.io/en/latest/source/getting_started/installation.html#manual-installation-dev-setup) to set up Lux for development purposes.
 
@@ -176,7 +178,7 @@ Lux is undergoing active development. If you are interested in using Lux, we wou
 
 Other additional resources:
 
-- Sign up for the early-user [mailing list](https://forms.gle/XKv3ejrshkCi3FJE6) to stay tuned for upcoming releases, updates, or user studies. 
+- Follow us on [Twitter](https://twitter.com/intent/follow?original_referer=https%3A%2F%2Fpublish.twitter.com%2F&ref_src=twsrc%5Etfw&screen_name=lux_api&tw_p=followbutton) or sign up to our [mailing list](https://forms.gle/XKv3ejrshkCi3FJE6) to stay tuned for upcoming releases and updates. 
 - Visit [ReadTheDoc](https://lux-api.readthedocs.io/en/latest/) for more detailed documentation.
 - Try out these hands-on [exercises](https://mybinder.org/v2/gh/lux-org/lux-binder/master?urlpath=tree/exercise) or [tutorials](https://mybinder.org/v2/gh/lux-org/lux-binder/master?urlpath=tree/tutorial) on [Binder](https://mybinder.org/v2/gh/lux-org/lux-binder/master). Or clone and run [lux-binder](https://github.com/lux-org/lux-binder) locally.
 - Join our community [Slack](https://communityinviter.com/apps/lux-project/lux) to discuss and ask questions.
diff --git a/lux/action/univariate.py b/lux/action/univariate.py
index e94af9b..e44e832 100644
--- a/lux/action/univariate.py
+++ b/lux/action/univariate.py
@@ -84,10 +84,13 @@ def univariate(ldf, *args):
             examples = f" (e.g., {possible_attributes[0]})"
         intent = [lux.Clause("?", data_type="geographical"), lux.Clause("?", data_model="measure")]
         intent.extend(filter_specs)
+        long_description = f"Geographical displays <a href='https://en.wikipedia.org/wiki/Choropleth_map'>choropleths</a> for geographic attribute{examples}, with colors indicating the average measure values. "
+        if lux.config.plotting_backend == "matplotlib":
+            long_description += "The map visualizations from the 'Geographical' tab are rendered using <a href='https://altair-viz.github.io/'>Altair</a>. Lux does not currently support geographical maps with Matplotlib. If you would like this feature, please leave us a comment at <a href='https://github.com/lux-org/lux/issues/310'>issue #310</a> to let us know!"
         recommendation = {
             "action": "Geographical",
             "description": "Show choropleth maps of <p class='highlight-descriptor'>geographic</p> attributes",
-            "long_description": f"Occurence displays choropleths of averages for some geographic attribute{examples}. Visualizations are ranked by diversity of the geographic attribute.",
+            "long_description": long_description,
         }
     elif data_type_constraint == "temporal":
         intent = [lux.Clause("?", data_type="temporal")]
diff --git a/lux/core/frame.py b/lux/core/frame.py
index c3d13f5..a57b355 100644
--- a/lux/core/frame.py
+++ b/lux/core/frame.py
@@ -317,10 +317,6 @@ class LuxDataFrame(pd.DataFrame):
     def current_vis(self, current_vis: Dict):
         self._current_vis = current_vis
 
-    def __repr__(self):
-        # TODO: _repr_ gets called from _repr_html, need to get rid of this call
-        return ""
-
     #######################################################
     ########## SQL Metadata, type, model schema ###########
     #######################################################
@@ -619,7 +615,7 @@ class LuxDataFrame(pd.DataFrame):
         self._widget.observe(self.remove_deleted_recs, names="deletedIndices")
         self._widget.observe(self.set_intent_on_click, names="selectedIntentIndex")
 
-    def _repr_html_(self):
+    def _ipython_display_(self):
         from IPython.display import display
         from IPython.display import clear_output
         import ipywidgets as widgets
@@ -628,48 +624,48 @@ class LuxDataFrame(pd.DataFrame):
             if self._pandas_only:
                 display(self.display_pandas())
                 self._pandas_only = False
-            # else:
-            if not self.index.nlevels >= 2 or self.columns.nlevels >= 2:
-                self.maintain_metadata()
+            else:
+                if not self.index.nlevels >= 2 or self.columns.nlevels >= 2:
+                    self.maintain_metadata()
 
-                if self._intent != [] and (not hasattr(self, "_compiled") or not self._compiled):
-                    from lux.processor.Compiler import Compiler
+                    if self._intent != [] and (not hasattr(self, "_compiled") or not self._compiled):
+                        from lux.processor.Compiler import Compiler
 
-                    self.current_vis = Compiler.compile_intent(self, self._intent)
+                        self.current_vis = Compiler.compile_intent(self, self._intent)
 
-            if lux.config.default_display == "lux":
-                self._toggle_pandas_display = False
-            else:
-                self._toggle_pandas_display = True
+                if lux.config.default_display == "lux":
+                    self._toggle_pandas_display = False
+                else:
+                    self._toggle_pandas_display = True
 
-            # df_to_display.maintain_recs() # compute the recommendations (TODO: This can be rendered in another thread in the background to populate self._widget)
-            self.maintain_recs()
+                # df_to_display.maintain_recs() # compute the recommendations (TODO: This can be rendered in another thread in the background to populate self._widget)
+                self.maintain_recs()
 
-            # Observers(callback_function, listen_to_this_variable)
-            self._widget.observe(self.remove_deleted_recs, names="deletedIndices")
-            self._widget.observe(self.set_intent_on_click, names="selectedIntentIndex")
+                # Observers(callback_function, listen_to_this_variable)
+                self._widget.observe(self.remove_deleted_recs, names="deletedIndices")
+                self._widget.observe(self.set_intent_on_click, names="selectedIntentIndex")
 
-            button = widgets.Button(
-                description="Toggle Pandas/Lux",
-                layout=widgets.Layout(width="140px", top="5px"),
-            )
-            self.output = widgets.Output()
-            display(button, self.output)
-
-            def on_button_clicked(b):
-                with self.output:
-                    if b:
-                        self._toggle_pandas_display = not self._toggle_pandas_display
-                    clear_output()
-                    if self._toggle_pandas_display:
-                        display(self.display_pandas())
-                    else:
-                        # b.layout.display = "none"
-                        display(self._widget)
-                        # b.layout.display = "inline-block"
-
-            button.on_click(on_button_clicked)
-            on_button_clicked(None)
+                button = widgets.Button(
+                    description="Toggle Pandas/Lux",
+                    layout=widgets.Layout(width="140px", top="5px"),
+                )
+                self.output = widgets.Output()
+                display(button, self.output)
+
+                def on_button_clicked(b):
+                    with self.output:
+                        if b:
+                            self._toggle_pandas_display = not self._toggle_pandas_display
+                        clear_output()
+                        if self._toggle_pandas_display:
+                            display(self.display_pandas())
+                        else:
+                            # b.layout.display = "none"
+                            display(self._widget)
+                            # b.layout.display = "inline-block"
+
+                button.on_click(on_button_clicked)
+                on_button_clicked(None)
 
         except (KeyboardInterrupt, SystemExit):
             raise
@@ -888,24 +884,22 @@ class LuxDataFrame(pd.DataFrame):
 
     # Overridden Pandas Functions
     def head(self, n: int = 5):
-        self._prev = self
-        self._history.append_event("head", n=5)
-        return super(LuxDataFrame, self).head(n)
+        ret_val = super(LuxDataFrame, self).head(n)
+        ret_val._prev = self
+        ret_val._history.append_event("head", n=5)
+        return ret_val
 
     def tail(self, n: int = 5):
-        self._prev = self
-        self._history.append_event("tail", n=5)
-        return super(LuxDataFrame, self).tail(n)
-
-    def info(self, *args, **kwargs):
-        self._pandas_only = True
-        self._history.append_event("info", *args, **kwargs)
-        return super(LuxDataFrame, self).info(*args, **kwargs)
+        ret_val = super(LuxDataFrame, self).tail(n)
+        ret_val._prev = self
+        ret_val._history.append_event("tail", n=5)
+        return ret_val
 
     def describe(self, *args, **kwargs):
-        self._pandas_only = True
-        self._history.append_event("describe", *args, **kwargs)
-        return super(LuxDataFrame, self).describe(*args, **kwargs)
+        ret_val = super(LuxDataFrame, self).describe(*args, **kwargs)
+        ret_val._pandas_only = True
+        ret_val._history.append_event("describe", *args, **kwargs)
+        return ret_val
 
     def groupby(self, *args, **kwargs):
         history_flag = False
diff --git a/lux/core/series.py b/lux/core/series.py
index 40cb8b5..a5e2def 100644
--- a/lux/core/series.py
+++ b/lux/core/series.py
@@ -105,7 +105,7 @@ class LuxSeries(pd.Series):
 
         return lux.core.originalSeries(self, copy=False)
 
-    def __repr__(self):
+    def _ipython_display_(self):
         from IPython.display import display
         from IPython.display import clear_output
         import ipywidgets as widgets
@@ -188,7 +188,6 @@ class LuxSeries(pd.Series):
             )
             warnings.warn(traceback.format_exc())
             display(self.to_pandas())
-        return ""
 
     @property
     def recommendation(self):
diff --git a/lux/executor/PandasExecutor.py b/lux/executor/PandasExecutor.py
index 3511578..911bd93 100644
--- a/lux/executor/PandasExecutor.py
+++ b/lux/executor/PandasExecutor.py
@@ -422,13 +422,8 @@ class PandasExecutor(Executor):
                 elif self._is_geographical_attribute(ldf[attr]):
                     ldf._data_type[attr] = "geographical"
                 elif pd.api.types.is_float_dtype(ldf.dtypes[attr]):
-                    # int columns gets coerced into floats if contain NaN
-                    convertible2int = pd.api.types.is_integer_dtype(ldf[attr].convert_dtypes())
-                    if (
-                        convertible2int
-                        and ldf.cardinality[attr] != len(ldf)
-                        and (len(ldf[attr].convert_dtypes().unique() < 20))
-                    ):
+
+                    if ldf.cardinality[attr] != len(ldf) and (ldf.cardinality[attr] < 20):
                         ldf._data_type[attr] = "nominal"
                     else:
                         ldf._data_type[attr] = "quantitative"
@@ -525,11 +520,8 @@ class PandasExecutor(Executor):
             else:
                 attribute_repr = attribute
 
-            if ldf.dtypes[attribute] != "float64" or ldf[attribute].isnull().values.any():
-                ldf.unique_values[attribute_repr] = list(ldf[attribute].unique())
-                ldf.cardinality[attribute_repr] = len(ldf.unique_values[attribute])
-            else:
-                ldf.cardinality[attribute_repr] = 999  # special value for non-numeric attribute
+            ldf.unique_values[attribute_repr] = list(ldf[attribute].unique())
+            ldf.cardinality[attribute_repr] = len(ldf.unique_values[attribute_repr])
 
             if pd.api.types.is_float_dtype(ldf.dtypes[attribute]) or pd.api.types.is_integer_dtype(
                 ldf.dtypes[attribute]
diff --git a/lux/vis/Vis.py b/lux/vis/Vis.py
index 30bdc96..a6a67ac 100644
--- a/lux/vis/Vis.py
+++ b/lux/vis/Vis.py
@@ -111,7 +111,7 @@ class Vis:
         self._intent = intent
         self.refresh_source(self._source)
 
-    def _repr_html_(self):
+    def _ipython_display_(self):
         from IPython.display import display
 
         check_import_lux_widget()
diff --git a/lux/vis/VisList.py b/lux/vis/VisList.py
index e3bdfa3..d1746f6 100644
--- a/lux/vis/VisList.py
+++ b/lux/vis/VisList.py
@@ -257,7 +257,7 @@ class VisList:
             if invert_order:
                 dobj.score = 1 - dobj.score
 
-    def _repr_html_(self):
+    def _ipython_display_(self):
         self._widget = None
         from IPython.display import display
         from lux.core.frame import LuxDataFrame
diff --git a/lux/vislib/altair/Choropleth.py b/lux/vislib/altair/Choropleth.py
index 37bf869..2e3e969 100644
--- a/lux/vislib/altair/Choropleth.py
+++ b/lux/vislib/altair/Choropleth.py
@@ -37,7 +37,7 @@ class Choropleth(AltairChart):
         super().__init__(dobj)
 
     def __repr__(self):
-        return f"Proportional Symbol Map <{str(self.vis)}>"
+        return f"Choropleth Map <{str(self.vis)}>"
 
     def initialize_chart(self):
         x_attr = self.vis.get_attr_by_channel("x")[0]
diff --git a/lux/vislib/matplotlib/BarChart.py b/lux/vislib/matplotlib/BarChart.py
index aefab75..6f706f7 100644
--- a/lux/vislib/matplotlib/BarChart.py
+++ b/lux/vislib/matplotlib/BarChart.py
@@ -62,7 +62,6 @@ class BarChart(MatplotlibChart):
             bar_attr = x_attr.attribute
 
         k = 10
-        self._topkcode = ""
         n_bars = len(self.data.iloc[:, 0].unique())
         if n_bars > k:  # Truncating to only top k
             remaining_bars = n_bars - k
@@ -79,17 +78,7 @@ class BarChart(MatplotlibChart):
                 color="#ff8e04",
             )
 
-            self._topkcode = f"""text = alt.Chart(visData).mark_text(
-			x=155, 
-			y=142,
-			align="right",
-			color = "#ff8e04",
-			fontSize = 11,
-			text=f"+ {remaining_bars} more ..."
-		)
-		chart = chart + text\n"""
-
-        df = pd.DataFrame(self.data)
+        df = self.data
 
         bars = df[bar_attr].apply(lambda x: str(x))
         measurements = df[measure_attr]
diff --git a/lux/vislib/matplotlib/Heatmap.py b/lux/vislib/matplotlib/Heatmap.py
index 3b2b2ab..c4f58b0 100644
--- a/lux/vislib/matplotlib/Heatmap.py
+++ b/lux/vislib/matplotlib/Heatmap.py
@@ -48,7 +48,7 @@ class Heatmap(MatplotlibChart):
         if len(y_attr.attribute) > 25:
             y_attr_abv = y_attr.attribute[:15] + "..." + y_attr.attribute[-10:]
 
-        df = pd.DataFrame(self.data)
+        df = self.data
 
         plot_code = ""
         color_attr = self.vis.get_attr_by_channel("color")
diff --git a/lux/vislib/matplotlib/Histogram.py b/lux/vislib/matplotlib/Histogram.py
index c4ef8f2..8aef029 100644
--- a/lux/vislib/matplotlib/Histogram.py
+++ b/lux/vislib/matplotlib/Histogram.py
@@ -49,7 +49,7 @@ class Histogram(MatplotlibChart):
 
         markbar = abs(x_max - x_min) / 12
 
-        df = pd.DataFrame(self.data)
+        df = self.data
 
         bars = df[msr_attr.attribute]
         measurements = df["Number of Records"]
diff --git a/lux/vislib/matplotlib/LineChart.py b/lux/vislib/matplotlib/LineChart.py
index db805dd..b2fd9f1 100644
--- a/lux/vislib/matplotlib/LineChart.py
+++ b/lux/vislib/matplotlib/LineChart.py
@@ -52,7 +52,7 @@ class LineChart(MatplotlibChart):
 
         self.data = self.data.dropna(subset=[x_attr.attribute, y_attr.attribute])
 
-        df = pd.DataFrame(self.data)
+        df = self.data
 
         x_pts = df[x_attr.attribute]
         y_pts = df[y_attr.attribute]
diff --git a/lux/vislib/matplotlib/MatplotlibRenderer.py b/lux/vislib/matplotlib/MatplotlibRenderer.py
index 30e91f7..6a5dd40 100644
--- a/lux/vislib/matplotlib/MatplotlibRenderer.py
+++ b/lux/vislib/matplotlib/MatplotlibRenderer.py
@@ -20,6 +20,7 @@ from lux.vislib.matplotlib.ScatterChart import ScatterChart
 from lux.vislib.matplotlib.LineChart import LineChart
 from lux.vislib.matplotlib.Histogram import Histogram
 from lux.vislib.matplotlib.Heatmap import Heatmap
+from lux.vislib.altair.AltairRenderer import AltairRenderer
 import matplotlib.pyplot as plt
 from lux.utils.utils import matplotlib_setup
 
@@ -81,6 +82,8 @@ class MatplotlibRenderer:
             chart = LineChart(vis, fig, ax)
         elif vis.mark == "heatmap":
             chart = Heatmap(vis, fig, ax)
+        elif vis.mark == "geographical":
+            return AltairRenderer().create_vis(vis, False)
         else:
             chart = None
             return chart
diff --git a/lux/vislib/matplotlib/ScatterChart.py b/lux/vislib/matplotlib/ScatterChart.py
index cb038ee..6829edc 100644
--- a/lux/vislib/matplotlib/ScatterChart.py
+++ b/lux/vislib/matplotlib/ScatterChart.py
@@ -48,7 +48,7 @@ class ScatterChart(MatplotlibChart):
         if len(y_attr.attribute) > 25:
             y_attr_abv = y_attr.attribute[:15] + "..." + y_attr.attribute[-10:]
 
-        df = pd.DataFrame(self.data)
+        df = self.data
 
         x_pts = df[x_attr.attribute]
         y_pts = df[y_attr.attribute]
@@ -66,7 +66,7 @@ class ScatterChart(MatplotlibChart):
             vals = [unique.index(i) for i in colors]
             if color_attr_type == "quantitative":
                 self.fig, self.ax = matplotlib_setup(7, 5)
-                set_fig_code = "fig, ax = plt.subplots(7, 5)\n"
+                set_fig_code = "fig, ax = plt.subplots(figsize=(7, 5))\n"
                 self.ax.scatter(x_pts, y_pts, c=vals, cmap="Blues", alpha=0.5)
                 plot_code += f"ax.scatter(x_pts, y_pts, c={vals}, cmap='Blues', alpha=0.5)\n"
                 my_cmap = plt.cm.get_cmap("Blues")
@@ -96,10 +96,10 @@ class ScatterChart(MatplotlibChart):
                         maxlen = len(unique[i])
                 if maxlen > 20:
                     self.fig, self.ax = matplotlib_setup(9, 5)
-                    set_fig_code = "fig, ax = plt.subplots(9, 5)\n"
+                    set_fig_code = "fig, ax = plt.subplots(figsize=(9, 5))\n"
                 else:
                     self.fig, self.ax = matplotlib_setup(7, 5)
-                    set_fig_code = "fig, ax = plt.subplots(7, 5)\n"
+                    set_fig_code = "fig, ax = plt.subplots(figsize=(7, 5))\n"
 
                 cmap = "Set1"
                 if len(unique) > 9:
@@ -131,7 +131,7 @@ class ScatterChart(MatplotlibChart):
                     fontsize='13')\n"""
                 plot_code += "scatter.set_alpha(0.5)\n"
         else:
-            set_fig_code = "fig, ax = plt.subplots(4.5, 4)\n"
+            set_fig_code = "fig, ax = plt.subplots(figsize=(4.5, 4))\n"
             self.ax.scatter(x_pts, y_pts, alpha=0.5)
             plot_code += f"ax.scatter(x_pts, y_pts, alpha=0.5)\n"
         self.ax.set_xlabel(x_attr_abv, fontsize="15")


Test patch:
diff --git a/tests/test_action.py b/tests/test_action.py
index 893c13b..5e22938 100644
--- a/tests/test_action.py
+++ b/tests/test_action.py
@@ -23,7 +23,7 @@ def test_vary_filter_val(global_var):
     df = pytest.olympic
     vis = Vis(["Height", "SportType=Ball"], df)
     df.set_intent_as_vis(vis)
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation["Filter"]) == len(df["SportType"].unique()) - 1
     linechart = list(filter(lambda x: x.mark == "line", df.recommendation["Enhance"]))[0]
     assert (
@@ -42,7 +42,7 @@ def test_filter_inequality(global_var):
             lux.Clause(attribute="Acceleration", filter_op=">", value=10),
         ]
     )
-    df._repr_html_()
+    df._ipython_display_()
 
     from lux.utils.utils import get_filter_specs
 
@@ -59,7 +59,7 @@ def test_generalize_action(global_var):
         df["Year"], format="%Y"
     )  # change pandas dtype for the column "Year" to datetype
     df.set_intent(["Acceleration", "MilesPerGal", "Cylinders", "Origin=USA"])
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation["Generalize"]) == 4
     v1 = df.recommendation["Generalize"][0]
     v2 = df.recommendation["Generalize"][1]
@@ -86,14 +86,14 @@ def test_row_column_group(global_var):
     tseries[tseries.columns.min()] = tseries[tseries.columns.min()].fillna(0)
     tseries[tseries.columns.max()] = tseries[tseries.columns.max()].fillna(tseries.max(axis=1))
     tseries = tseries.interpolate("zero", axis=1)
-    tseries._repr_html_()
+    tseries._ipython_display_()
     assert list(tseries.recommendation.keys()) == ["Temporal"]
 
 
 def test_groupby(global_var):
     df = pytest.college_df
     groupbyResult = df.groupby("Region").sum()
-    groupbyResult._repr_html_()
+    groupbyResult._ipython_display_()
     assert list(groupbyResult.recommendation.keys()) == ["Column Groups"]
 
 
@@ -160,7 +160,7 @@ def test_crosstab():
 
     df = pd.DataFrame(d, columns=["Name", "Exam", "Subject", "Result"])
     result = pd.crosstab([df.Exam], df.Result)
-    result._repr_html_()
+    result._ipython_display_()
     assert list(result.recommendation.keys()) == ["Row Groups", "Column Groups"]
 
 
@@ -169,7 +169,7 @@ def test_custom_aggregation(global_var):
 
     df = pytest.college_df
     df.set_intent(["HighestDegree", lux.Clause("AverageCost", aggregation=np.ptp)])
-    df._repr_html_()
+    df._ipython_display_()
     assert list(df.recommendation.keys()) == ["Enhance", "Filter", "Generalize"]
     df.clear_intent()
 
@@ -178,7 +178,7 @@ def test_year_filter_value(global_var):
     df = pytest.car_df
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     df.set_intent(["Acceleration", "Horsepower"])
-    df._repr_html_()
+    df._ipython_display_()
     list_of_vis_with_year_filter = list(
         filter(
             lambda vis: len(
@@ -210,7 +210,7 @@ def test_similarity(global_var):
             lux.Clause("Origin=USA"),
         ]
     )
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation["Similarity"]) == 2
     ranked_list = df.recommendation["Similarity"]
 
@@ -264,7 +264,7 @@ def test_similarity2():
 def test_intent_retained():
     df = pd.read_csv("https://raw.githubusercontent.com/lux-org/lux-datasets/master/data/employee.csv")
     df.intent = ["Attrition"]
-    df._repr_html_()
+    df._ipython_display_()
 
     df["%WorkingYearsAtCompany"] = df["YearsAtCompany"] / df["TotalWorkingYears"]
     assert df.current_vis != None
@@ -272,5 +272,5 @@ def test_intent_retained():
     assert df._recs_fresh == False
     assert df._metadata_fresh == False
 
-    df._repr_html_()
+    df._ipython_display_()
     assert list(df.recommendation.keys()) == ["Enhance", "Filter"]
diff --git a/tests/test_compiler.py b/tests/test_compiler.py
index 3c72563..76e7034 100644
--- a/tests/test_compiler.py
+++ b/tests/test_compiler.py
@@ -81,17 +81,17 @@ def test_underspecified_single_vis(global_var, test_recs):
 
 def test_set_intent_as_vis(global_var, test_recs):
     df = pytest.car_df
-    df._repr_html_()
+    df._ipython_display_()
     vis = df.recommendation["Correlation"][0]
     df.intent = vis
-    df._repr_html_()
+    df._ipython_display_()
     test_recs(df, ["Enhance", "Filter", "Generalize"])
 
 
 @pytest.fixture
 def test_recs():
     def test_recs_function(df, actions):
-        df._repr_html_()
+        df._ipython_display_()
         assert len(df.recommendation) > 0
         recKeys = list(df.recommendation.keys())
         list_equal(recKeys, actions)
@@ -350,7 +350,7 @@ def test_populate_options(global_var):
             lux.Clause(attribute="MilesPerGal"),
         ]
     )
-    df._repr_html_()
+    df._ipython_display_()
     col_set = set()
     for specOptions in Compiler.populate_wildcard_options(df._intent, df)["attributes"]:
         for clause in specOptions:
@@ -372,7 +372,7 @@ def test_remove_all_invalid(global_var):
             lux.Clause(attribute="Origin"),
         ]
     )
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.current_vis) == 0
     df.clear_intent()
 
diff --git a/tests/test_config.py b/tests/test_config.py
index 8cc5acd..18c2da7 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -51,7 +51,7 @@ def register_new_action(validator: bool = True):
 
 def test_default_actions_registered(global_var):
     df = pytest.car_df
-    df._repr_html_()
+    df._ipython_display_()
     assert "Distribution" in df.recommendation
     assert len(df.recommendation["Distribution"]) > 0
 
@@ -67,7 +67,7 @@ def test_default_actions_registered(global_var):
 
 def test_fail_validator():
     df = register_new_action()
-    df._repr_html_()
+    df._ipython_display_()
     assert (
         "bars" not in df.recommendation,
         "Bars should not be rendered when there is no intent 'horsepower' specified.",
@@ -77,7 +77,7 @@ def test_fail_validator():
 def test_pass_validator():
     df = register_new_action()
     df.set_intent(["Acceleration", "Horsepower"])
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation["bars"]) > 0
     assert (
         "bars" in df.recommendation,
@@ -87,7 +87,7 @@ def test_pass_validator():
 
 def test_no_validator():
     df = register_new_action(False)
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation["bars"]) > 0
     assert "bars" in df.recommendation
 
@@ -121,7 +121,7 @@ def test_invalid_validator(global_var):
 def test_remove_action():
     df = register_new_action()
     df.set_intent(["Acceleration", "Horsepower"])
-    df._repr_html_()
+    df._ipython_display_()
     assert (
         "bars" in df.recommendation,
         "Bars should be rendered after it has been registered with correct intent.",
@@ -131,7 +131,7 @@ def test_remove_action():
         "Bars should be rendered after it has been registered with correct intent.",
     )
     lux.config.remove_action("bars")
-    df._repr_html_()
+    df._ipython_display_()
     assert (
         "bars" not in df.recommendation,
         "Bars should not be rendered after it has been removed.",
@@ -148,22 +148,22 @@ def test_remove_invalid_action(global_var):
 # TODO: This test does not pass in pytest but is working in Jupyter notebook.
 def test_remove_default_actions(global_var):
     df = pytest.car_df
-    df._repr_html_()
+    df._ipython_display_()
 
     lux.config.remove_action("distribution")
-    df._repr_html_()
+    df._ipython_display_()
     assert "Distribution" not in df.recommendation
 
     lux.config.remove_action("occurrence")
-    df._repr_html_()
+    df._ipython_display_()
     assert "Occurrence" not in df.recommendation
 
     lux.config.remove_action("temporal")
-    df._repr_html_()
+    df._ipython_display_()
     assert "Temporal" not in df.recommendation
 
     lux.config.remove_action("correlation")
-    df._repr_html_()
+    df._ipython_display_()
     assert "Correlation" not in df.recommendation
 
     assert (
@@ -173,7 +173,7 @@ def test_remove_default_actions(global_var):
 
     df = register_new_action()
     df.set_intent(["Acceleration", "Horsepower"])
-    df._repr_html_()
+    df._ipython_display_()
     assert (
         "bars" in df.recommendation,
         "Bars should be rendered after it has been registered with correct intent.",
@@ -195,7 +195,7 @@ def test_matplotlib_set_default_plotting_style():
 
     df = pd.read_csv("lux/data/car.csv")
     lux.config.plotting_style = add_title
-    df._repr_html_()
+    df._ipython_display_()
     title_addition = 'ax.set_title("Test Title")'
     exported_code_str = df.recommendation["Correlation"][0].to_Altair()
     assert title_addition in exported_code_str
@@ -211,7 +211,7 @@ def test_set_default_plotting_style():
 
     df = pd.read_csv("lux/data/car.csv")
     lux.config.plotting_style = change_color_make_transparent_add_title
-    df._repr_html_()
+    df._ipython_display_()
     config_mark_addition = 'chart = chart.configure_mark(color="green", opacity=0.2)'
     title_addition = 'chart.title = "Test Title"'
     exported_code_str = df.recommendation["Correlation"][0].to_Altair()
@@ -221,23 +221,23 @@ def test_set_default_plotting_style():
 
 def test_sampling_flag_config():
     df = pd.read_csv("https://raw.githubusercontent.com/lux-org/lux-datasets/master/data/airbnb_nyc.csv")
-    df._repr_html_()
+    df._ipython_display_()
     assert df.recommendation["Correlation"][0].data.shape[0] == 30000
     lux.config.sampling = False
     df = df.copy()
-    df._repr_html_()
+    df._ipython_display_()
     assert df.recommendation["Correlation"][0].data.shape[0] == 48895
     lux.config.sampling = True
 
 
 def test_sampling_parameters_config():
     df = pd.read_csv("lux/data/car.csv")
-    df._repr_html_()
+    df._ipython_display_()
     assert df.recommendation["Correlation"][0].data.shape[0] == 392
     lux.config.sampling_start = 50
     lux.config.sampling_cap = 100
     df = pd.read_csv("lux/data/car.csv")
-    df._repr_html_()
+    df._ipython_display_()
     assert df.recommendation["Correlation"][0].data.shape[0] == 100
     lux.config.sampling_cap = 30000
     lux.config.sampling_start = 10000
@@ -245,11 +245,11 @@ def test_sampling_parameters_config():
 
 def test_heatmap_flag_config():
     df = pd.read_csv("https://raw.githubusercontent.com/lux-org/lux-datasets/master/data/airbnb_nyc.csv")
-    df._repr_html_()
+    df._ipython_display_()
     assert df.recommendation["Correlation"][0]._postbin
     lux.config.heatmap = False
     df = pd.read_csv("https://raw.githubusercontent.com/lux-org/lux-datasets/master/data/airbnb_nyc.csv")
-    df._repr_html_()
+    df._ipython_display_()
     assert not df.recommendation["Correlation"][0]._postbin
     lux.config.heatmap = True
 
@@ -257,11 +257,11 @@ def test_heatmap_flag_config():
 def test_topk(global_var):
     df = pd.read_csv("lux/data/college.csv")
     lux.config.topk = False
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation["Correlation"]) == 45, "Turn off top K"
     lux.config.topk = 20
     df = pd.read_csv("lux/data/college.csv")
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation["Correlation"]) == 20, "Show top 20"
     for vis in df.recommendation["Correlation"]:
         assert vis.score > 0.2
@@ -270,20 +270,20 @@ def test_topk(global_var):
 def test_sort(global_var):
     df = pd.read_csv("lux/data/college.csv")
     lux.config.topk = 15
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation["Correlation"]) == 15, "Show top 15"
     for vis in df.recommendation["Correlation"]:
         assert vis.score > 0.5
     df = pd.read_csv("lux/data/college.csv")
     lux.config.sort = "ascending"
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation["Correlation"]) == 15, "Show bottom 15"
     for vis in df.recommendation["Correlation"]:
         assert vis.score < 0.35
 
     lux.config.sort = "none"
     df = pd.read_csv("lux/data/college.csv")
-    df._repr_html_()
+    df._ipython_display_()
     scorelst = [x.score for x in df.recommendation["Distribution"]]
     assert sorted(scorelst) != scorelst, "unsorted setting"
     lux.config.sort = "descending"
@@ -300,7 +300,7 @@ def test_sort(global_var):
 
 # 	df.plot_config = change_color_add_title
 
-# 	df._repr_html_()
+# 	df._ipython_display_()
 
 # 	vis_code = df.recommendation["Correlation"][0].to_Altair()
 # 	print (vis_code)
diff --git a/tests/test_dates.py b/tests/test_dates.py
index dc530fc..d6295b0 100644
--- a/tests/test_dates.py
+++ b/tests/test_dates.py
@@ -88,7 +88,7 @@ def test_refresh_inplace():
         }
     )
     with pytest.warns(UserWarning, match="Lux detects that the attribute 'date' may be temporal."):
-        df._repr_html_()
+        df._ipython_display_()
     assert df.data_type["date"] == "temporal"
 
     from lux.vis.Vis import Vis
diff --git a/tests/test_display.py b/tests/test_display.py
index 7716867..96ee644 100644
--- a/tests/test_display.py
+++ b/tests/test_display.py
@@ -26,16 +26,22 @@ def test_to_pandas(global_var):
 
 def test_display_LuxDataframe(global_var):
     df = pytest.car_df
-    df._repr_html_()
+    df._ipython_display_()
 
 
 def test_display_Vis(global_var):
     df = pytest.car_df
     vis = Vis(["Horsepower", "Acceleration"], df)
-    vis._repr_html_()
+    vis._ipython_display_()
 
 
 def test_display_VisList(global_var):
     df = pytest.car_df
     vislist = VisList(["?", "Acceleration"], df)
-    vislist._repr_html_()
+    vislist._ipython_display_()
+
+
+def test_repr(global_var):
+    df = pytest.car_df
+    output = df.__repr__()
+    assert "MilesPerGal" in output
diff --git a/tests/test_error_warning.py b/tests/test_error_warning.py
index 6106bfb..d4d7285 100644
--- a/tests/test_error_warning.py
+++ b/tests/test_error_warning.py
@@ -56,7 +56,7 @@ def test_vis_private_properties(global_var):
 
     df = pytest.car_df
     vis = Vis(["Horsepower", "Weight"], df)
-    vis._repr_html_()
+    vis._ipython_display_()
     assert isinstance(vis.data, lux.core.frame.LuxDataFrame)
     with pytest.raises(AttributeError, match="can't set attribute"):
         vis.data = "some val"
@@ -77,10 +77,10 @@ def test_vis_private_properties(global_var):
 # Test DataFrame Properties give Lux Warning but not UserWarning
 def test_lux_warnings(global_var):
     df = pd.DataFrame()
-    df._repr_html_()
+    df._ipython_display_()
     assert df._widget.message == f"<ul><li>Lux cannot operate on an empty DataFrame.</li></ul>"
     df = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
-    df._repr_html_()
+    df._ipython_display_()
     assert (
         df._widget.message
         == f"<ul><li>The DataFrame is too small to visualize. To generate visualizations in Lux, the DataFrame must contain at least 5 rows.</li></ul>"
@@ -88,7 +88,7 @@ def test_lux_warnings(global_var):
     df = pytest.car_df
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     new_df = df.set_index(["Name", "Cylinders"])
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert (
         new_df._widget.message
         == f"<ul><li>Lux does not currently support visualizations in a DataFrame with hierarchical indexes.\nPlease convert the DataFrame into a flat table via pandas.DataFrame.reset_index.</li></ul>"
diff --git a/tests/test_groupby.py b/tests/test_groupby.py
index b5841cc..724c524 100644
--- a/tests/test_groupby.py
+++ b/tests/test_groupby.py
@@ -19,54 +19,54 @@ import pandas as pd
 
 def test_agg(global_var):
     df = pytest.car_df
-    df._repr_html_()
+    df._ipython_display_()
     new_df = df[["Horsepower", "Brand"]].groupby("Brand").agg(sum)
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert new_df.history[0].name == "groupby"
     assert new_df.pre_aggregated
 
 
 def test_shortcut_agg(global_var):
     df = pytest.car_df
-    df._repr_html_()
+    df._ipython_display_()
     new_df = df[["MilesPerGal", "Brand"]].groupby("Brand").sum()
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert new_df.history[0].name == "groupby"
     assert new_df.pre_aggregated
 
 
 def test_agg_mean(global_var):
     df = pytest.car_df
-    df._repr_html_()
+    df._ipython_display_()
     new_df = df.groupby("Origin").mean()
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert new_df.history[0].name == "groupby"
     assert new_df.pre_aggregated
 
 
 def test_agg_size(global_var):
     df = pytest.car_df
-    df._repr_html_()
+    df._ipython_display_()
     new_df = df.groupby("Brand").size().to_frame()
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert new_df.history[0].name == "groupby"
     assert new_df.pre_aggregated
 
 
 def test_filter(global_var):
     df = pytest.car_df
-    df._repr_html_()
+    df._ipython_display_()
     new_df = df.groupby("Origin").filter(lambda x: x["Weight"].mean() > 3000)
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert new_df.history[0].name == "groupby"
     assert not new_df.pre_aggregated
 
 
 def test_get_group(global_var):
     df = pytest.car_df
-    df._repr_html_()
+    df._ipython_display_()
     new_df = df.groupby("Origin").get_group("Japan")
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert new_df.history[0].name == "groupby"
     assert not new_df.pre_aggregated
 
diff --git a/tests/test_interestingness.py b/tests/test_interestingness.py
index a549890..703fa44 100644
--- a/tests/test_interestingness.py
+++ b/tests/test_interestingness.py
@@ -25,7 +25,7 @@ def test_interestingness_1_0_0(global_var):
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
 
     df.set_intent([lux.Clause(attribute="Origin")])
-    df._repr_html_()
+    df._ipython_display_()
     # check that top recommended enhance graph score is not none and that ordering makes intuitive sense
     assert interestingness(df.recommendation["Enhance"][0], df) != None
     rank1 = -1
@@ -69,7 +69,7 @@ def test_interestingness_1_0_1(global_var):
             lux.Clause(attribute="Cylinders"),
         ]
     )
-    df._repr_html_()
+    df._ipython_display_()
     assert df.current_vis[0].score == 0
     df.clear_intent()
 
@@ -79,7 +79,7 @@ def test_interestingness_0_1_0(global_var):
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
 
     df.set_intent([lux.Clause(attribute="Horsepower")])
-    df._repr_html_()
+    df._ipython_display_()
     # check that top recommended enhance graph score is not none and that ordering makes intuitive sense
     assert interestingness(df.recommendation["Enhance"][0], df) != None
     rank1 = -1
@@ -129,7 +129,7 @@ def test_interestingness_0_1_1(global_var):
             lux.Clause(attribute="MilesPerGal"),
         ]
     )
-    df._repr_html_()
+    df._ipython_display_()
     assert interestingness(df.recommendation["Current Vis"][0], df) != None
     assert str(df.recommendation["Current Vis"][0]._inferred_intent[2].value) == "USA"
     df.clear_intent()
@@ -140,7 +140,7 @@ def test_interestingness_1_1_0(global_var):
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
 
     df.set_intent([lux.Clause(attribute="Horsepower"), lux.Clause(attribute="Year")])
-    df._repr_html_()
+    df._ipython_display_()
     # check that top recommended Enhance graph score is not none (all graphs here have same score)
     assert interestingness(df.recommendation["Enhance"][0], df) != None
 
@@ -176,7 +176,7 @@ def test_interestingness_1_1_1(global_var):
             lux.Clause(attribute="Origin", filter_op="=", value="USA", bin_size=20),
         ]
     )
-    df._repr_html_()
+    df._ipython_display_()
     # check that top recommended Enhance graph score is not none and that ordering makes intuitive sense
     assert interestingness(df.recommendation["Enhance"][0], df) != None
     rank1 = -1
@@ -227,7 +227,7 @@ def test_interestingness_0_2_0(global_var):
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
 
     df.set_intent([lux.Clause(attribute="Horsepower"), lux.Clause(attribute="Acceleration")])
-    df._repr_html_()
+    df._ipython_display_()
     # check that top recommended enhance graph score is not none and that ordering makes intuitive sense
     assert interestingness(df.recommendation["Enhance"][0], df) != None
     rank1 = -1
@@ -263,7 +263,7 @@ def test_interestingness_0_2_1(global_var):
             lux.Clause(attribute="Acceleration", filter_op=">", value=10),
         ]
     )
-    df._repr_html_()
+    df._ipython_display_()
     # check that top recommended Generalize graph score is not none
     assert interestingness(df.recommendation["Generalize"][0], df) != None
     df.clear_intent()
@@ -273,25 +273,28 @@ def test_interestingness_deviation_nan():
     import numpy as np
 
     dataset = [
-        {"date": "2017-08-25 09:06:11+00:00", "category": "A", "value": 25.0},
-        {"date": "2017-08-25 09:06:11+00:00", "category": "B", "value": 1.2},
-        {"date": "2017-08-25 09:06:11+00:00", "category": "C", "value": 1.3},
-        {"date": "2017-08-25 09:06:11+00:00", "category": "D", "value": 1.4},
-        {"date": "2017-08-25 09:06:11+00:00", "category": "E", "value": 1.5},
-        {"date": "2017-08-25 09:06:11+00:00", "category": "F", "value": 0.1},
+        {"date": "2017-08-25", "category": "A", "value": 25.0},
+        {"date": "2017-08-25", "category": "B", "value": 1.2},
+        {"date": "2017-08-25", "category": "C", "value": 1.3},
+        {"date": "2017-08-25", "category": "D", "value": 1.4},
+        {"date": "2017-08-25", "category": "E", "value": 1.5},
+        {"date": "2017-08-25", "category": "F", "value": 0.1},
         {"date": np.nan, "category": "C", "value": 0.2},
         {"date": np.nan, "category": "B", "value": 0.2},
         {"date": np.nan, "category": "F", "value": 0.3},
         {"date": np.nan, "category": "E", "value": 0.3},
         {"date": np.nan, "category": "D", "value": 0.4},
         {"date": np.nan, "category": "A", "value": 10.4},
-        {"date": "2017-07-25 15:06:11+00:00", "category": "A", "value": 15.5},
-        {"date": "2017-07-25 15:06:11+00:00", "category": "F", "value": 1.0},
-        {"date": "2017-07-25 15:06:11+00:00", "category": "B", "value": 0.1},
+        {"date": "2017-07-25", "category": "A", "value": 15.5},
+        {"date": "2017-07-25", "category": "F", "value": 1.0},
+        {"date": "2017-07-25", "category": "B", "value": 0.1},
     ]
     test = pd.DataFrame(dataset)
     from lux.vis.Vis import Vis
 
+    test["date"] = pd.to_datetime(test["date"], format="%Y-%M-%d")
+    test.set_data_type({"value": "quantitative"})
+
     vis = Vis(["date", "value", "category=A"], test)
     vis2 = Vis(["date", "value", "category=B"], test)
     from lux.interestingness.interestingness import interestingness
diff --git a/tests/test_maintainence.py b/tests/test_maintainence.py
index 4e18994..447fff6 100644
--- a/tests/test_maintainence.py
+++ b/tests/test_maintainence.py
@@ -21,15 +21,15 @@ from lux.vis.Vis import Vis
 
 def test_metadata_subsequent_display(global_var):
     df = pytest.car_df
-    df._repr_html_()
+    df._ipython_display_()
     assert df._metadata_fresh == True, "Failed to maintain metadata after display df"
-    df._repr_html_()
+    df._ipython_display_()
     assert df._metadata_fresh == True, "Failed to maintain metadata after display df"
 
 
 def test_metadata_subsequent_vis(global_var):
     df = pytest.car_df
-    df._repr_html_()
+    df._ipython_display_()
     assert df._metadata_fresh == True, "Failed to maintain metadata after display df"
     vis = Vis(["Acceleration", "Horsepower"], df)
     assert df._metadata_fresh == True, "Failed to maintain metadata after display df"
@@ -37,7 +37,7 @@ def test_metadata_subsequent_vis(global_var):
 
 def test_metadata_inplace_operation(global_var):
     df = pytest.car_df
-    df._repr_html_()
+    df._ipython_display_()
     assert df._metadata_fresh == True, "Failed to maintain metadata after display df"
     df.dropna(inplace=True)
     assert df._metadata_fresh == False, "Failed to expire metadata after in-place Pandas operation"
@@ -45,7 +45,7 @@ def test_metadata_inplace_operation(global_var):
 
 def test_metadata_new_df_operation(global_var):
     df = pytest.car_df
-    df._repr_html_()
+    df._ipython_display_()
     assert df._metadata_fresh == True, "Failed to maintain metadata after display df"
     df[["MilesPerGal", "Acceleration"]]
     assert df._metadata_fresh == True, "Failed to maintain metadata after display df"
@@ -61,7 +61,7 @@ def test_metadata_column_group_reset_df(global_var):
     result = df.groupby("Cylinders").mean()
     assert not hasattr(result, "_metadata_fresh")
     # Note that this should trigger two compute metadata (one for df, and one for an intermediate df.reset_index used to feed inside created Vis)
-    result._repr_html_()
+    result._ipython_display_()
     assert result._metadata_fresh == True, "Failed to maintain metadata after display df"
 
     colgroup_recs = result.recommendation["Column Groups"]
@@ -72,12 +72,12 @@ def test_metadata_column_group_reset_df(global_var):
 
 def test_recs_inplace_operation(global_var):
     df = pytest.college_df
-    df._repr_html_()
+    df._ipython_display_()
     assert df._recs_fresh == True, "Failed to maintain recommendation after display df"
     assert len(df.recommendation["Occurrence"]) == 6
     df.drop(columns=["Name"], inplace=True)
     assert "Name" not in df.columns, "Failed to perform `drop` operation in-place"
     assert df._recs_fresh == False, "Failed to maintain recommendation after in-place Pandas operation"
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation["Occurrence"]) == 5
     assert df._recs_fresh == True, "Failed to maintain recommendation after display df"
diff --git a/tests/test_nan.py b/tests/test_nan.py
index 1701215..7003468 100644
--- a/tests/test_nan.py
+++ b/tests/test_nan.py
@@ -24,7 +24,7 @@ def test_nan_column(global_var):
     df = pytest.college_df
     old_geo = df["Geography"]
     df["Geography"] = np.nan
-    df._repr_html_()
+    df._ipython_display_()
     for visList in df.recommendation.keys():
         for vis in df.recommendation[visList]:
             assert vis.get_attr_by_attr_name("Geography") == []
@@ -84,7 +84,7 @@ def test_apply_nan_filter():
     test = pd.DataFrame(dataset)
 
     vis = Vis(["some_nan", "some_nan2=nan"], test)
-    vis._repr_html_()
+    vis._ipython_display_()
     assert vis.mark == "bar"
 
 
@@ -111,5 +111,5 @@ def test_nan_series_occurence():
     }
     nan_series = LuxSeries(dvalues)
     ldf = pd.DataFrame(nan_series, columns=["col"])
-    ldf._repr_html_()
+    ldf._ipython_display_()
     assert ldf.recommendation["Occurrence"][0].mark == "bar"
diff --git a/tests/test_pandas.py b/tests/test_pandas.py
index 4c8f896..db0f958 100644
--- a/tests/test_pandas.py
+++ b/tests/test_pandas.py
@@ -19,16 +19,16 @@ import pandas as pd
 
 def test_head_tail(global_var):
     df = pytest.car_df
-    df._repr_html_()
+    df._ipython_display_()
     assert df._message.to_html() == ""
-    df.head()._repr_html_()
+    df.head()._ipython_display_()
     assert (
         "Lux is visualizing the previous version of the dataframe before you applied <code>head</code>."
         in df._message.to_html()
     )
-    df._repr_html_()
+    df._ipython_display_()
     assert df._message.to_html() == ""
-    df.tail()._repr_html_()
+    df.tail()._ipython_display_()
     assert (
         "Lux is visualizing the previous version of the dataframe before you applied <code>tail</code>."
         in df._message.to_html()
@@ -38,12 +38,12 @@ def test_head_tail(global_var):
 def test_describe(global_var):
     df = pytest.college_df
     summary = df.describe()
-    summary._repr_html_()
+    summary._ipython_display_()
     assert len(summary.columns) == 10
 
 
 def test_convert_dtype(global_var):
     df = pytest.college_df
     cdf = df.convert_dtypes()
-    cdf._repr_html_()
+    cdf._ipython_display_()
     assert list(cdf.recommendation.keys()) == ["Correlation", "Distribution", "Occurrence"]
diff --git a/tests/test_pandas_coverage.py b/tests/test_pandas_coverage.py
index 87e282a..fc8451c 100644
--- a/tests/test_pandas_coverage.py
+++ b/tests/test_pandas_coverage.py
@@ -26,20 +26,20 @@ import warnings
 def test_deepcopy(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
-    df._repr_html_()
+    df._ipython_display_()
     saved_df = df.copy(deep=True)
-    saved_df._repr_html_()
+    saved_df._ipython_display_()
     check_metadata_equal(df, saved_df)
 
 
 def test_rename_inplace(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
-    df._repr_html_()
+    df._ipython_display_()
     new_df = df.copy(deep=True)
     df.rename(columns={"Name": "Car Name"}, inplace=True)
-    df._repr_html_()
-    new_df._repr_html_()
+    df._ipython_display_()
+    new_df._ipython_display_()
     # new_df is the old dataframe (df) with the new column name changed inplace
     new_df, df = df, new_df
 
@@ -79,9 +79,9 @@ def test_rename_inplace(global_var):
 def test_rename(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
-    df._repr_html_()
+    df._ipython_display_()
     new_df = df.rename(columns={"Name": "Car Name"}, inplace=False)
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert df.data_type != new_df.data_type
 
     assert df.data_type["Name"] == new_df.data_type["Car Name"]
@@ -131,7 +131,7 @@ def test_rename3(global_var):
         "col9",
         "col10",
     ]
-    df._repr_html_()
+    df._ipython_display_()
     assert list(df.recommendation.keys()) == [
         "Correlation",
         "Distribution",
@@ -147,7 +147,7 @@ def test_concat(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     new_df = pd.concat([df.loc[:, "Name":"Cylinders"], df.loc[:, "Year":"Origin"]], axis="columns")
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert list(new_df.recommendation.keys()) == [
         "Distribution",
         "Occurrence",
@@ -160,7 +160,7 @@ def test_groupby_agg(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     new_df = df.groupby("Year").agg(sum)
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert list(new_df.recommendation.keys()) == ["Column Groups"]
     assert len(new_df.cardinality) == 7
 
@@ -168,7 +168,7 @@ def test_groupby_agg(global_var):
 def test_groupby_agg_big(global_var):
     df = pd.read_csv("lux/data/car.csv")
     new_df = df.groupby("Brand").agg(sum)
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert list(new_df.recommendation.keys()) == ["Column Groups"]
     assert len(new_df.cardinality) == 8
     year_vis = list(
@@ -180,7 +180,7 @@ def test_groupby_agg_big(global_var):
     assert year_vis.mark == "bar"
     assert year_vis.get_attr_by_channel("x")[0].attribute == "Year"
     new_df = new_df.T
-    new_df._repr_html_()
+    new_df._ipython_display_()
     year_vis = list(
         filter(
             lambda vis: vis.get_attr_by_attr_name("Year") != [],
@@ -195,13 +195,13 @@ def test_qcut(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     df["Weight"] = pd.qcut(df["Weight"], q=3)
-    df._repr_html_()
+    df._ipython_display_()
 
 
 def test_cut(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Weight"] = pd.cut(df["Weight"], bins=[0, 2500, 7500, 10000], labels=["small", "medium", "large"])
-    df._repr_html_()
+    df._ipython_display_()
 
 
 def test_groupby_agg_very_small(global_var):
@@ -209,7 +209,7 @@ def test_groupby_agg_very_small(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     new_df = df.groupby("Origin").agg(sum).reset_index()
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert list(new_df.recommendation.keys()) == ["Column Groups"]
     assert len(new_df.cardinality) == 7
 
@@ -219,7 +219,7 @@ def test_groupby_agg_very_small(global_var):
 #     df = pd.read_csv(url)
 #     df["Year"] = pd.to_datetime(df["Year"], format='%Y')
 #     new_df = df.groupby(["Year", "Cylinders"]).agg(sum).stack().reset_index()
-#     new_df._repr_html_()
+#     new_df._ipython_display_()
 #     assert list(new_df.recommendation.keys() ) == ['Column Groups'] # TODO
 #     assert len(new_df.cardinality) == 7 # TODO
 
@@ -228,7 +228,7 @@ def test_query(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     new_df = df.query("Weight > 3000")
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert list(new_df.recommendation.keys()) == [
         "Correlation",
         "Distribution",
@@ -242,7 +242,7 @@ def test_pop(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     df.pop("Weight")
-    df._repr_html_()
+    df._ipython_display_()
     assert list(df.recommendation.keys()) == [
         "Correlation",
         "Distribution",
@@ -256,8 +256,8 @@ def test_transform(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     new_df = df.iloc[:, 1:].groupby("Origin").transform(sum)
-    new_df._repr_html_()
-    assert list(new_df.recommendation.keys()) == ["Correlation", "Distribution", "Occurrence"]
+    new_df._ipython_display_()
+    assert list(new_df.recommendation.keys()) == ["Occurrence"]
     assert len(new_df.cardinality) == 7
 
 
@@ -266,7 +266,7 @@ def test_get_group(global_var):
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     gbobj = df.groupby("Origin")
     new_df = gbobj.get_group("Japan")
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert list(new_df.recommendation.keys()) == [
         "Correlation",
         "Distribution",
@@ -281,7 +281,7 @@ def test_applymap(global_var):
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     mapping = {"USA": 0, "Europe": 1, "Japan": 2}
     df["Origin"] = df[["Origin"]].applymap(mapping.get)
-    df._repr_html_()
+    df._ipython_display_()
     assert list(df.recommendation.keys()) == [
         "Correlation",
         "Distribution",
@@ -295,7 +295,7 @@ def test_strcat(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     df["combined"] = df["Origin"].str.cat(df["Brand"], sep=", ")
-    df._repr_html_()
+    df._ipython_display_()
     assert list(df.recommendation.keys()) == [
         "Correlation",
         "Distribution",
@@ -313,7 +313,7 @@ def test_named_agg(global_var):
         max_weight=("Weight", "max"),
         mean_displacement=("Displacement", "mean"),
     )
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert list(new_df.recommendation.keys()) == ["Column Groups"]
     assert len(new_df.cardinality) == 4
 
@@ -322,7 +322,7 @@ def test_change_dtype(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     df["Cylinders"] = pd.Series(df["Cylinders"], dtype="Int64")
-    df._repr_html_()
+    df._ipython_display_()
     assert list(df.recommendation.keys()) == [
         "Correlation",
         "Distribution",
@@ -336,7 +336,7 @@ def test_get_dummies(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     new_df = pd.get_dummies(df)
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert list(new_df.recommendation.keys()) == [
         "Correlation",
         "Distribution",
@@ -351,7 +351,7 @@ def test_drop(global_var):
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     new_df = df.drop([0, 1, 2], axis="rows")
     new_df2 = new_df.drop(["Name", "MilesPerGal", "Cylinders"], axis="columns")
-    new_df2._repr_html_()
+    new_df2._ipython_display_()
     assert list(new_df2.recommendation.keys()) == [
         "Correlation",
         "Distribution",
@@ -366,7 +366,7 @@ def test_merge(global_var):
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     new_df = df.drop([0, 1, 2], axis="rows")
     new_df2 = pd.merge(df, new_df, how="left", indicator=True)
-    new_df2._repr_html_()
+    new_df2._ipython_display_()
     assert list(new_df2.recommendation.keys()) == [
         "Correlation",
         "Distribution",
@@ -380,7 +380,7 @@ def test_prefix(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     new_df = df.add_prefix("1_")
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert list(new_df.recommendation.keys()) == [
         "Correlation",
         "Distribution",
@@ -395,7 +395,7 @@ def test_loc(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     new_df = df.loc[:, "Displacement":"Origin"]
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert list(new_df.recommendation.keys()) == [
         "Correlation",
         "Distribution",
@@ -404,18 +404,18 @@ def test_loc(global_var):
     ]
     assert len(new_df.cardinality) == 6
     new_df = df.loc[0:10, "Displacement":"Origin"]
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert list(new_df.recommendation.keys()) == ["Correlation", "Distribution", "Occurrence"]
     assert len(new_df.cardinality) == 6
     new_df = df.loc[0:10, "Displacement":"Horsepower"]
-    new_df._repr_html_()
-    assert list(new_df.recommendation.keys()) == ["Distribution", "Occurrence"]
+    new_df._ipython_display_()
+    assert list(new_df.recommendation.keys()) == ["Correlation", "Distribution"]
     assert len(new_df.cardinality) == 2
     import numpy as np
 
     inter_df = df.groupby("Brand")[["Acceleration", "Weight", "Horsepower"]].agg(np.mean)
     new_df = inter_df.loc["chevrolet":"fiat", "Acceleration":"Weight"]
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert list(new_df.recommendation.keys()) == ["Column Groups"]
     assert len(new_df.cardinality) == 3
 
@@ -424,7 +424,7 @@ def test_iloc(global_var):
     df = pd.read_csv("lux/data/car.csv")
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     new_df = df.iloc[:, 3:9]
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert list(new_df.recommendation.keys()) == [
         "Correlation",
         "Distribution",
@@ -433,18 +433,18 @@ def test_iloc(global_var):
     ]
     assert len(new_df.cardinality) == 6
     new_df = df.iloc[0:11, 3:9]
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert list(new_df.recommendation.keys()) == ["Correlation", "Distribution", "Occurrence"]
     assert len(new_df.cardinality) == 6
     new_df = df.iloc[0:11, 3:5]
-    new_df._repr_html_()
-    assert list(new_df.recommendation.keys()) == ["Distribution", "Occurrence"]
+    new_df._ipython_display_()
+    assert list(new_df.recommendation.keys()) == ["Correlation", "Distribution"]
     assert len(new_df.cardinality) == 2
     import numpy as np
 
     inter_df = df.groupby("Brand")[["Acceleration", "Weight", "Horsepower"]].agg(np.mean)
     new_df = inter_df.iloc[5:10, 0:2]
-    new_df._repr_html_()
+    new_df._ipython_display_()
     assert list(new_df.recommendation.keys()) == ["Column Groups"]
     assert len(new_df.cardinality) == 3
 
@@ -521,29 +521,29 @@ def test_index(global_var):
     df = df.set_index(["Name"])
     # if this assert fails, then the index column has not properly been removed from the dataframe's column and registered as an index
     assert "Name" not in df.columns and df.index.name == "Name"
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation) > 0
     df = df.reset_index()
     assert "Name" in df.columns and df.index.name != "Name"
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation) > 0
 
     df.set_index(["Name"], inplace=True)
     assert "Name" not in df.columns and df.index.name == "Name"
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation) > 0
     df.reset_index(inplace=True)
     assert "Name" in df.columns and df.index.name != "Name"
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation) > 0
 
     df = df.set_index(["Name"])
     assert "Name" not in df.columns and df.index.name == "Name"
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation) > 0
     df = df.reset_index(drop=True)
     assert "Name" not in df.columns and df.index.name != "Name"
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation) > 0
 
 
@@ -551,17 +551,17 @@ def test_index_col(global_var):
     df = pd.read_csv("lux/data/car.csv", index_col="Name")
     # if this assert fails, then the index column has not properly been removed from the dataframe's column and registered as an index
     assert "Name" not in df.columns and df.index.name == "Name"
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation) > 0
     df = df.reset_index()
     assert "Name" in df.columns and df.index.name != "Name"
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.recommendation) > 0
 
     # this case is not yet addressed, need to have a check that eliminates bar charts with duplicate column names
     # df = df.set_index(["Name"], drop=False)
     # assert "Name" not in df.columns and df.index.name == "Name"
-    # df._repr_html_()
+    # df._ipython_display_()
     # assert len(df.recommendation) > 0
     # df = df.reset_index(drop=True)
     # assert "Name" not in df.columns and df.index.name != "Name"
@@ -575,7 +575,7 @@ def test_index_col(global_var):
 def test_df_to_series(global_var):
     # Ensure metadata is kept when going from df to series
     df = pd.read_csv("lux/data/car.csv")
-    df._repr_html_()  # compute metadata
+    df._ipython_display_()  # compute metadata
     assert df.cardinality is not None
     series = df["Weight"]
     assert isinstance(series, lux.core.series.LuxSeries), "Derived series is type LuxSeries."
@@ -589,7 +589,7 @@ def test_df_to_series(global_var):
 
 def test_value_counts(global_var):
     df = pd.read_csv("lux/data/car.csv")
-    df._repr_html_()  # compute metadata
+    df._ipython_display_()  # compute metadata
     assert df.cardinality is not None
     series = df["Weight"]
     series.value_counts()
@@ -603,7 +603,7 @@ def test_value_counts(global_var):
 
 def test_str_replace(global_var):
     df = pd.read_csv("lux/data/car.csv")
-    df._repr_html_()  # compute metadata
+    df._ipython_display_()  # compute metadata
     assert df.cardinality is not None
     series = df["Brand"].str.replace("chevrolet", "chevy")
     assert isinstance(series, lux.core.series.LuxSeries), "Derived series is type LuxSeries."
@@ -622,7 +622,7 @@ def test_str_replace(global_var):
 def test_read_json(global_var):
     url = "https://raw.githubusercontent.com/lux-org/lux-datasets/master/data/car.json"
     df = pd.read_json(url)
-    df._repr_html_()
+    df._ipython_display_()
     assert list(df.recommendation.keys()) == [
         "Correlation",
         "Distribution",
@@ -635,7 +635,7 @@ def test_read_json(global_var):
 def test_read_sas(global_var):
     url = "https://github.com/lux-org/lux-datasets/blob/master/data/airline.sas7bdat?raw=true"
     df = pd.read_sas(url, format="sas7bdat")
-    df._repr_html_()
+    df._ipython_display_()
     assert list(df.recommendation.keys()) == ["Correlation", "Distribution", "Temporal"]
     assert len(df.data_type) == 6
 
@@ -644,5 +644,5 @@ def test_read_multi_dtype(global_var):
     url = "https://github.com/lux-org/lux-datasets/blob/master/data/car-data.xls?raw=true"
     df = pd.read_excel(url)
     with pytest.warns(UserWarning, match="mixed type") as w:
-        df._repr_html_()
+        df._ipython_display_()
         assert "df['Car Type'] = df['Car Type'].astype(str)" in str(w[-1].message)
diff --git a/tests/test_parser.py b/tests/test_parser.py
index 333977a..bac6d45 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -78,7 +78,7 @@ def test_case5(global_var):
 def test_case6(global_var):
     df = pytest.car_df
     df.set_intent(["Horsepower", "Origin=?"])
-    df._repr_html_()
+    df._ipython_display_()
     assert type(df._intent[0]) is lux.Clause
     assert df._intent[0].attribute == "Horsepower"
     assert type(df._intent[1]) is lux.Clause
@@ -90,7 +90,7 @@ def test_case6(global_var):
 def test_case7(global_var):
     df = pytest.car_df
     df.intent = [["Horsepower", "MilesPerGal", "Acceleration"], "Origin"]
-    df._repr_html_()
+    df._ipython_display_()
     assert len(df.current_vis) == 3
     df.clear_intent()
 
diff --git a/tests/test_performance.py b/tests/test_performance.py
index 256d45f..fca6a1c 100644
--- a/tests/test_performance.py
+++ b/tests/test_performance.py
@@ -23,10 +23,10 @@ import time
 def test_q1_performance_census(global_var):
     df = pd.read_csv("https://github.com/lux-org/lux-datasets/blob/master/data/census.csv?raw=true")
     tic = time.perf_counter()
-    df._repr_html_()
+    df._ipython_display_()
     toc = time.perf_counter()
     delta = toc - tic
-    df._repr_html_()
+    df._ipython_display_()
     toc2 = time.perf_counter()
     delta2 = toc2 - toc
     print(f"1st display Performance: {delta:0.4f} seconds")
diff --git a/tests/test_series.py b/tests/test_series.py
index ec7a758..0c0ff66 100644
--- a/tests/test_series.py
+++ b/tests/test_series.py
@@ -20,7 +20,7 @@ import warnings
 def test_df_to_series():
     # Ensure metadata is kept when going from df to series
     df = pd.read_csv("lux/data/car.csv")
-    df._repr_html_()  # compute metadata
+    df._ipython_display_()  # compute metadata
     assert df.cardinality is not None
     series = df["Weight"]
     assert isinstance(series, lux.core.series.LuxSeries), "Derived series is type LuxSeries."
diff --git a/tests/test_type.py b/tests/test_type.py
index 8376220..8b57d00 100644
--- a/tests/test_type.py
+++ b/tests/test_type.py
@@ -38,7 +38,7 @@ def test_check_int_id():
     df = pd.read_csv(
         "https://github.com/lux-org/lux-datasets/blob/master/data/instacart_sample.csv?raw=true"
     )
-    df._repr_html_()
+    df._ipython_display_()
     inverted_data_type = lux.config.executor.invert_data_type(df.data_type)
     assert len(inverted_data_type["id"]) == 3
     assert (
@@ -49,7 +49,7 @@ def test_check_int_id():
 
 def test_check_str_id():
     df = pd.read_csv("https://github.com/lux-org/lux-datasets/blob/master/data/churn.csv?raw=true")
-    df._repr_html_()
+    df._ipython_display_()
     assert (
         "<code>customerID</code> is not visualized since it resembles an ID field.</li>"
         in df._message.to_html()
@@ -228,7 +228,7 @@ def test_set_data_type():
         "https://github.com/lux-org/lux-datasets/blob/master/data/real_estate_tutorial.csv?raw=true"
     )
     with pytest.warns(UserWarning) as w:
-        df._repr_html_()
+        df._ipython_display_()
         assert "starter template that you can use" in str(w[-1].message)
         assert "df.set_data_type" in str(w[-1].message)
 
@@ -237,7 +237,7 @@ def test_set_data_type():
     assert df.data_type["Year"] == "nominal"
     with warnings.catch_warnings() as w:
         warnings.simplefilter("always")
-        df._repr_html_()
+        df._ipython_display_()
         assert not w
 
 
diff --git a/tests/test_vis.py b/tests/test_vis.py
index 532dcf5..e5fa0d0 100644
--- a/tests/test_vis.py
+++ b/tests/test_vis.py
@@ -79,7 +79,7 @@ def test_refresh_collection(global_var):
     df = pytest.car_df
     df["Year"] = pd.to_datetime(df["Year"], format="%Y")
     df.set_intent([lux.Clause(attribute="Acceleration"), lux.Clause(attribute="Horsepower")])
-    df._repr_html_()
+    df._ipython_display_()
     enhanceCollection = df.recommendation["Enhance"]
     enhanceCollection.refresh_source(df[df["Origin"] == "USA"])
     df.clear_intent()
@@ -168,10 +168,10 @@ def test_vis_set_intent(global_var):
 
     df = pytest.car_df
     vis = Vis(["Weight", "Horsepower"], df)
-    vis._repr_html_()
+    vis._ipython_display_()
     assert "Horsepower" in str(vis._code)
     vis.intent = ["Weight", "MilesPerGal"]
-    vis._repr_html_()
+    vis._ipython_display_()
     assert "MilesPerGal" in str(vis._code)
 
 
@@ -180,11 +180,11 @@ def test_vis_list_set_intent(global_var):
 
     df = pytest.car_df
     vislist = VisList(["Horsepower", "?"], df)
-    vislist._repr_html_()
+    vislist._ipython_display_()
     for vis in vislist:
         assert vis.get_attr_by_attr_name("Horsepower") != []
     vislist.intent = ["Weight", "?"]
-    vislist._repr_html_()
+    vislist._ipython_display_()
     for vis in vislist:
         assert vis.get_attr_by_attr_name("Weight") != []
 
@@ -194,7 +194,7 @@ def test_text_not_overridden():
 
     df = pd.read_csv("lux/data/college.csv")
     vis = Vis(["Region", "Geography"], df)
-    vis._repr_html_()
+    vis._ipython_display_()
     code = vis.to_Altair()
     assert 'color = "#ff8e04"' in code
 
@@ -438,7 +438,7 @@ def test_colored_heatmap_chart(global_var):
 def test_vegalite_default_actions_registered(global_var):
     df = pytest.car_df
     lux.config.plotting_backend = "vegalite"
-    df._repr_html_()
+    df._ipython_display_()
     # Histogram Chart
     assert "Distribution" in df.recommendation
     assert len(df.recommendation["Distribution"]) > 0
@@ -465,7 +465,7 @@ def test_vegalite_default_actions_registered_2(global_var):
     df["magnitude"] = np.random.randint(0, 20, size=len(df))
     lux.config.plotting_backend = "vegalite"
 
-    # Symbol Map
+    # Choropleth Map
     assert "Geographical" in df.recommendation
     assert len(df.recommendation["Geographical"]) > 0
 
@@ -481,7 +481,7 @@ def test_vegalite_default_actions_registered_2(global_var):
 def test_matplotlib_default_actions_registered(global_var):
     lux.config.plotting_backend = "matplotlib"
     df = pytest.car_df
-    df._repr_html_()
+    df._ipython_display_()
     # Histogram Chart
     assert "Distribution" in df.recommendation
     assert len(df.recommendation["Distribution"]) > 0
@@ -499,10 +499,32 @@ def test_matplotlib_default_actions_registered(global_var):
     assert len(df.recommendation["Correlation"]) > 0
 
 
+def test_matplotlib_default_actions_registered_2(global_var):
+    import numpy as np
+
+    df = pd.read_csv(
+        "https://raw.githubusercontent.com/altair-viz/vega_datasets/master/vega_datasets/_data/airports.csv"
+    )
+    df["magnitude"] = np.random.randint(0, 20, size=len(df))
+    lux.config.plotting_backend = "matplotlib"
+
+    # Choropleth Map
+    assert "Geographical" in df.recommendation
+    assert len(df.recommendation["Geographical"]) > 0
+
+    # Occurrence Chart
+    assert "Occurrence" in df.recommendation
+    assert len(df.recommendation["Occurrence"]) > 0
+
+    # Scatter Chart
+    assert "Correlation" in df.recommendation
+    assert len(df.recommendation["Correlation"]) > 0
+
+
 def test_vegalite_heatmap_flag_config():
     df = pd.read_csv("https://raw.githubusercontent.com/lux-org/lux-datasets/master/data/airbnb_nyc.csv")
     lux.config.plotting_backend = "vegalite"
-    df._repr_html_()
+    df._ipython_display_()
     # Heatmap Chart
     assert df.recommendation["Correlation"][0]._postbin
     lux.config.heatmap = False
@@ -516,7 +538,7 @@ def test_vegalite_heatmap_flag_config():
 def test_matplotlib_heatmap_flag_config():
     df = pd.read_csv("https://raw.githubusercontent.com/lux-org/lux-datasets/master/data/airbnb_nyc.csv")
     lux.config.plotting_backend = "matplotlib"
-    df._repr_html_()
+    df._ipython_display_()
     # Heatmap Chart
     assert df.recommendation["Correlation"][0]._postbin
     lux.config.heatmap = False