Repository: spyder-ide/spyder

Issue:
DataFrames in Variable Explorer: Missings should have distinctive background color
### Issue Report Checklist

* [x] Searched the [issues page](https://github.com/spyder-ide/spyder/issues?q=is%3Aissue) for similar reports
* [x] Read the relevant sections of the [Spyder Troubleshooting Guide](https://github.com/spyder-ide/spyder/wiki/Troubleshooting-Guide-and-FAQ) and followed its advice
* [ ] Reproduced the issue after updating with ``conda update spyder`` (or ``pip``, if not using Anaconda)
* [ ] Could not reproduce inside ``jupyter qtconsole`` (if console-related)
* [ ] Tried basic troubleshooting (if a bug/error)
    * [ ] Restarted Spyder
    * [ ] Reset preferences with ``spyder --reset``
    * [ ] Reinstalled the latest version of [Anaconda](https://www.anaconda.com/download/)
    * [ ] Tried the other applicable steps from the Troubleshooting Guide
* [x] Completed the **Problem Description**, **Steps to Reproduce** and **Version** sections below


## Problem Description
When opening a Pandas DataFrame with missing values in the Variable Explorer, the missings are displayed with red cell background, which is similar to the red background of the minimal values. So the missings are difficult to spot.

I suggest using a white background for the missings instead.

### What steps reproduce the problem?

1. `df=pd.DataFrame([1,None,5,9])`
2. Open df in the Variable Explorer.

### What is the expected output? What do you see instead?

I see
![screenshot-missings-in-variable-explorer](https://user-images.githubusercontent.com/21648/46651707-28d4ad80-cba1-11e8-8fcb-6ce5290b1e7d.png)

I expect the nan field to have a visually distinctive color, e.g. white.

## Versions

* Spyder version: 3.3.1
* Python version: 3.7.0 64bits
* Qt version: Qt 5.9.3
* PyQt version: 5.9.2
* Operating System name/version: Win7 64-bit

(everything from WinPython64-3.7.0.2)

### Dependencies

Available on request.


Discussion:
That's a very good suggestion, but (unfortunately) we don't have the time to implement it. Probably after Spyder 4 is released.
That's fine. I am simply using this patch against `spyder\\widgets\\variableexplorer\\dataframeeditor.py` for now:

```python
@@ -228,6 +228,8 @@ class DataFrameModel(QAbstractTableModel):
         if not self.bgcolor_enabled:
             return
         value = self.get_value(index.row(), column-1)
+        if np.isnan(value):
+            return Qt.white
         if self.max_min_col[column - 1] is None:
             color = QColor(BACKGROUND_NONNUMBER_COLOR)
             if is_text_string(value):
```

Resolving patch:
diff --git a/spyder/plugins/variableexplorer/widgets/dataframeeditor.py b/spyder/plugins/variableexplorer/widgets/dataframeeditor.py
--- a/spyder/plugins/variableexplorer/widgets/dataframeeditor.py
+++ b/spyder/plugins/variableexplorer/widgets/dataframeeditor.py
@@ -45,7 +45,7 @@
                             QMessageBox, QPushButton, QTableView,
                             QScrollBar, QTableWidget, QFrame,
                             QItemDelegate)
-from pandas import DataFrame, Index, Series
+from pandas import DataFrame, Index, Series, isna
 try:
     from pandas._libs.tslib import OutOfBoundsDatetime
 except ImportError:  # For pandas version < 0.20
@@ -272,7 +272,7 @@ def get_bgcolor(self, index):
         if not self.bgcolor_enabled:
             return
         value = self.get_value(index.row(), column)
-        if self.max_min_col[column] is None:
+        if self.max_min_col[column] is None or isna(value):
             color = QColor(BACKGROUND_NONNUMBER_COLOR)
             if is_text_string(value):
                 color.setAlphaF(BACKGROUND_STRING_ALPHA)


Test patch:
diff --git a/spyder/plugins/variableexplorer/widgets/tests/test_dataframeeditor.py b/spyder/plugins/variableexplorer/widgets/tests/test_dataframeeditor.py
--- a/spyder/plugins/variableexplorer/widgets/tests/test_dataframeeditor.py
+++ b/spyder/plugins/variableexplorer/widgets/tests/test_dataframeeditor.py
@@ -276,6 +276,27 @@ def test_dataframemodel_get_bgcolor_with_object():
     a = dataframeeditor.BACKGROUND_MISC_ALPHA
     assert colorclose(bgcolor(dfm, 0, 0), (h, s, v, a))
 
+
+def test_dataframemodel_get_bgcolor_with_missings():
+    """
+    Test that df bg colors are correct for missing values of various types.
+
+    The types `bool`, `object`, `datetime`, and `timedelta` are omitted,
+    because missings have no different background there yet.
+    """
+    df = DataFrame({'int': [1, None], 'float': [.1, None],
+                    'complex': [1j, None], 'string': ['a', None]})
+    df['category'] = df['string'].astype('category')
+    dfm = DataFrameModel(df)
+    h, s, v, __ = QColor(dataframeeditor.BACKGROUND_NONNUMBER_COLOR).getHsvF()
+    alpha = dataframeeditor.BACKGROUND_MISC_ALPHA
+    for idx, column in enumerate(df.columns):
+        assert not colorclose(bgcolor(dfm, 0, idx), (h, s, v, alpha)), \
+            'Wrong bg color for value of type ' + column
+        assert colorclose(bgcolor(dfm, 1, idx), (h, s, v, alpha)), \
+            'Wrong bg color for missing of type ' + column
+
+
 def test_dataframemodel_with_format_percent_d_and_nan():
     """
     Test DataFrameModel with format `%d` and dataframe containing NaN