Repository: alteryx/woodwork (python)

Issue:
Index column with NaN will always return invalid schema
Our check in `get_invalid_schema_message` for whether the underlying index exactly matches the Woodwork index column uses `all(dataframe.index == dataframe[schema.index])`, which means NaNs will not evaluate to True, so we say that the schema is invalid. 


```python
df = pd.DataFrame({'id':pd.Series([5,4,None,2], dtype='float64'), 'col':pd.Series(['b','b','b','d'], dtype='category')})
df.ww.init(index='id')
schema = df.ww.schema

assert not ww.is_schema_valid(df, schema)
```
We should add a test case with nans in the index column and add a fix that includes nans in the check.

This came up in a Featuretools test for `add_last_time_index` where we use `update_dataframe`.


Pull request description:
Allow NaNs in schema validation check
- Stops indicating that the schema is invalid if there are null values in the index column
- Closes #861 

Patch:
diff --git a/docs/source/release_notes.rst b/docs/source/release_notes.rst
index d86b2e2..251bbb0 100644
--- a/docs/source/release_notes.rst
+++ b/docs/source/release_notes.rst
@@ -7,6 +7,7 @@ Release Notes
         * Add ``is_schema_valid`` and ``get_invalid_schema_message`` functions for checking schema validity (:pr:`834`)
     * Fixes
         * Raise error when a column is set as the index and time index (:pr:`859`)
+        * Allow NaNs in index for schema validation check (:pr:`862`)
     * Changes
         * Consistently use ``ColumnNotPresentError`` for mismatches between user input and dataframe/schema columns (:pr:`837`)
         * Raise custom ``WoodworkNotInitError`` when accessing Woodwork attributes before initialization (:pr:`838`)
@@ -17,7 +18,7 @@ Release Notes
         * Update README.md with non-nullable dtypes in code example (:pr:`856`)
 
     Thanks to the following people for contributing to this release:
-    :user:`jeff-hernandez`, :user:`gsheni`, :user:`rwedge`, :user:`thehomebrewnerd`
+    :user:`jeff-hernandez`, :user:`gsheni`, :user:`rwedge`, :user:`tamargrey`, :user:`thehomebrewnerd`
 
 **v0.2.0 April 20, 2021**
     .. warning::
diff --git a/woodwork/accessor_utils.py b/woodwork/accessor_utils.py
index 2a8b0b5..799360d 100644
--- a/woodwork/accessor_utils.py
+++ b/woodwork/accessor_utils.py
@@ -153,7 +153,7 @@ def get_invalid_schema_message(dataframe, schema):
                 f'{df_dtype}, and {schema.logical_types[name]} dtype, {valid_dtype}'
     if schema.index is not None and isinstance(dataframe, pd.DataFrame):
         # Index validation not performed for Dask/Koalas
-        if not all(dataframe.index == dataframe[schema.index]):
+        if not pd.Series(dataframe.index, dtype=dataframe[schema.index].dtype).equals(pd.Series(dataframe[schema.index].values)):
             return 'Index mismatch between DataFrame and typing information'
         elif not dataframe[schema.index].is_unique:
             return 'Index column is not unique'


Test patch:
diff --git a/woodwork/tests/accessor/test_accessor_utils.py b/woodwork/tests/accessor/test_accessor_utils.py
index 56a032a..614012e 100644
--- a/woodwork/tests/accessor/test_accessor_utils.py
+++ b/woodwork/tests/accessor/test_accessor_utils.py
@@ -181,6 +181,12 @@ def test_get_invalid_schema_message_index_checks(sample_df):
     not_unique_df.index.name = None
     assert get_invalid_schema_message(not_unique_df, schema) == 'Index column is not unique'
 
+    nan_df = pd.DataFrame({'id': pd.Series([5, 4, None, 2], dtype='float64'), 'col': pd.Series(['b', 'b', 'b', 'd'], dtype='category')})
+    nan_df.ww.init(index='id')
+    nan_df_schema = nan_df.ww.schema
+
+    assert get_invalid_schema_message(nan_df, nan_df_schema) is None
+
 
 def test_is_schema_valid_true(sample_df):
     sample_df.ww.init(index='id', logical_types={'phone_number': 'Categorical'})