Repository: lux-org/lux

Issue:
ValueError: cannot specify integer `bins` when input data contains infinity [BUG]
Trying to open a dataframe from a .csv that contains numpy.inf values fails with this error:

```
import lux, pandas
df = pandas.read_csv('filepath')
```
```
C:\Users\???\anaconda\envs\base_up_to_date\lib\site-packages\IPython\core\formatters.py:918: UserWarning:
Unexpected error in rendering Lux widget and recommendations. Falling back to Pandas display.
Please report the following issue on Github: https://github.com/lux-org/lux/issues 

C:\Users\???\anaconda\envs\base_up_to_date\lib\site-packages\lux\core\frame.py:632: UserWarning:Traceback (most recent call last):
  File "C:\Users\???\anaconda\envs\base_up_to_date\lib\site-packages\lux\core\frame.py", line 594, in _ipython_display_
    self.maintain_recs()
  File "C:\Users\???\anaconda\envs\base_up_to_date\lib\site-packages\lux\core\frame.py", line 436, in maintain_recs
    custom_action_collection = custom_actions(rec_df)
  File "C:\Users\???\anaconda\envs\base_up_to_date\lib\site-packages\lux\action\custom.py", line 76, in custom_actions
    recommendation = lux.config.actions[action_name].action(ldf)
  File "C:\Users\???\anaconda\envs\base_up_to_date\lib\site-packages\lux\action\correlation.py", line 50, in correlation
    vlist = VisList(intent, ldf)
  File "C:\Users\???\anaconda\envs\base_up_to_date\lib\site-packages\lux\vis\VisList.py", line 43, in __init__
    self.refresh_source(self._source)
  File "C:\Users\???\anaconda\envs\base_up_to_date\lib\site-packages\lux\vis\VisList.py", line 336, in refresh_source
    lux.config.executor.execute(self._collection, ldf, approx=approx)
  File "C:\Users\???\anaconda\envs\base_up_to_date\lib\site-packages\lux\executor\PandasExecutor.py", line 146, in execute
    PandasExecutor.execute_2D_binning(vis)
  File "C:\Users\???\anaconda\envs\base_up_to_date\lib\site-packages\lux\executor\PandasExecutor.py", line 387, in execute_2D_binning
    vis._vis_data["xBin"] = pd.cut(vis._vis_data[x_attr], bins=lux.config.heatmap_bin_size)
  File "C:\Users\???\anaconda\envs\base_up_to_date\lib\site-packages\pandas\core\reshape\tile.py", line 244, in cut
    "cannot specify integer `bins` when input data contains infinity"
ValueError: cannot specify integer `bins` when input data contains infinity
```

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/lux-org/lux/pull/442?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lux-org) Report
> Merging [#442](https://codecov.io/gh/lux-org/lux/pull/442?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lux-org) (7df184e) into [master](https://codecov.io/gh/lux-org/lux/commit/91e8e9885668bd42e1a125247a0d3166273b2a9a?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lux-org) (91e8e98) will **increase** coverage by `0.06%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/lux-org/lux/pull/442/graphs/tree.svg?width=650&height=150&src=pr&token=skTUnFpwwX&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lux-org)](https://codecov.io/gh/lux-org/lux/pull/442?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lux-org)

```diff
@@            Coverage Diff             @@
##           master     #442      +/-   ##
==========================================
+ Coverage   65.55%   65.62%   +0.06%     
==========================================
  Files          55       55              
  Lines        4419     4422       +3     
==========================================
+ Hits         2897     2902       +5     
+ Misses       1522     1520       -2     
```


| [Impacted Files](https://codecov.io/gh/lux-org/lux/pull/442?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lux-org) | Coverage Δ | |
|---|---|---|
| [lux/executor/PandasExecutor.py](https://codecov.io/gh/lux-org/lux/pull/442/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lux-org#diff-bHV4L2V4ZWN1dG9yL1BhbmRhc0V4ZWN1dG9yLnB5) | `89.84% <100.00%> (+0.09%)` | :arrow_up: |
| [lux/vislib/altair/ScatterChart.py](https://codecov.io/gh/lux-org/lux/pull/442/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lux-org#diff-bHV4L3Zpc2xpYi9hbHRhaXIvU2NhdHRlckNoYXJ0LnB5) | `96.96% <0.00%> (+3.03%)` | :arrow_up: |
| [lux/vislib/altair/Heatmap.py](https://codecov.io/gh/lux-org/lux/pull/442/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lux-org#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/442?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lux-org).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lux-org)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/lux-org/lux/pull/442?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lux-org). Last update [91e8e98...7df184e](https://codecov.io/gh/lux-org/lux/pull/442?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lux-org). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lux-org).


Patch:
diff --git a/lux/executor/PandasExecutor.py b/lux/executor/PandasExecutor.py
index 30dfdf4..8d2314c 100644
--- a/lux/executor/PandasExecutor.py
+++ b/lux/executor/PandasExecutor.py
@@ -281,6 +281,8 @@ class PandasExecutor(Executor):
         """
         import numpy as np
 
+        vis._vis_data = vis._vis_data.replace([np.inf, -np.inf], np.nan)
+
         bin_attribute = [x for x in vis._inferred_intent if x.bin_size != 0][0]
         bin_attr = bin_attribute.attribute
         series = vis.data[bin_attr]
@@ -379,6 +381,10 @@ class PandasExecutor(Executor):
         ----------
         vis : Vis
         """
+        import numpy as np
+
+        vis._vis_data = vis._vis_data.replace([np.inf, -np.inf], np.nan)
+
         pd.reset_option("mode.chained_assignment")
         with pd.option_context("mode.chained_assignment", None):
             x_attr = vis.get_attr_by_channel("x")[0].attribute


Test patch:
diff --git a/tests/test_pandas.py b/tests/test_pandas.py
index 6f3dea8..6bc23bb 100644
--- a/tests/test_pandas.py
+++ b/tests/test_pandas.py
@@ -15,6 +15,7 @@
 from .context import lux
 import pytest
 import pandas as pd
+import numpy as np
 
 
 def test_head_tail(global_var):
@@ -54,3 +55,21 @@ def test_convert_dtype(global_var):
     cdf = df.convert_dtypes()
     cdf._ipython_display_()
     assert list(cdf.recommendation.keys()) == ["Correlation", "Distribution", "Occurrence"]
+
+
+def test_infs():
+    nrows = 100_000
+
+    # continuous
+    c1 = np.random.uniform(0, 1, size=nrows)
+    c1[2] = np.inf
+    c2 = np.random.uniform(0, 1, size=nrows)
+    c2[3] = np.inf
+
+    # discrete
+    d1 = np.random.randint(0, 2, size=nrows)
+    d2 = np.random.randint(0, 2, size=nrows)
+
+    df = pd.DataFrame({"c1": c1, "c2": c2, "d1": d1, "d2": d2})
+
+    df._ipython_display_()