Repository: dirty-cat/dirty_cat

Issue:
MinHashEncoder does not understand "None" as missing value
The following raises an error because the None is not captured as a NaN:
```python
import numpy as np

a = np.array([['a', 'b', None, 'c']], dtype=object).T

from dirty_cat import MinHashEncoder

enc = MinHashEncoder()
enc.fit_transform(a)
```


Discussion:
jovan-stojanovic: LGTM, merging!

Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index f774809..49769fe 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -3,12 +3,21 @@
 Release 0.4.0
 =============
 
-Minor changes
+Major changes
 -------------
 
 * Unnecessary API has been made private: everything (files, functions, classes)
   starting with an underscore shouldn't be imported in your code.
 
+Minor changes
+-------------
+
+Bug fixes
+---------
+
+* :class:`MinHashEncoder` now considers `None` as missing values, rather
+  than raising an error.
+
 Release 0.3.0
 =============
 
@@ -55,7 +64,7 @@ Notes
 Release 0.2.2
 =============
 
-Bug-fixes
+Bug fixes
 ---------
 
 * Fixed a bug in the :class:`SuperVectorizer` causing a `FutureWarning`
diff --git a/dirty_cat/_minhash_encoder.py b/dirty_cat/_minhash_encoder.py
index 96a9a6e..8c6c86c 100644
--- a/dirty_cat/_minhash_encoder.py
+++ b/dirty_cat/_minhash_encoder.py
@@ -26,6 +26,7 @@ from ._fast_hash import ngram_min_hash
 from ._string_distances import get_unique_ngrams
 from ._utils import LRUDict, check_input
 
+NoneType = type(None)
 
 class MinHashEncoder(BaseEstimator, TransformerMixin):
     """
@@ -208,7 +209,8 @@ class MinHashEncoder(BaseEstimator, TransformerMixin):
             for k in range(X.shape[1]):
                 X_in = X[:, k].reshape(-1)
                 for i, x in enumerate(X_in):
-                    if isinstance(x, float):  # true if x is a missing value
+                    if (isinstance(x, float)  # true if x is a missing value
+                        or x is None):
                         is_nan_idx = True
                     elif x not in self.hash_dict_:
                         X_out[i, k * self.n_components : counter] = self.hash_dict_[


Test patch:
diff --git a/dirty_cat/tests/test_minhash_encoder.py b/dirty_cat/tests/test_minhash_encoder.py
index b55f56d..c640fb0 100644
--- a/dirty_cat/tests/test_minhash_encoder.py
+++ b/dirty_cat/tests/test_minhash_encoder.py
@@ -133,6 +133,15 @@ def test_missing_values(input_type: str, missing: str, hashing: str) -> None:
     return
 
 
+def test_missing_values_none():
+    # Test that "None" is also understood as a missing value
+    a = np.array([['a', 'b', None, 'c']], dtype=object).T
+
+    enc = MinHashEncoder()
+    d = enc.fit_transform(a)
+    np.testing.assert_array_equal(d[2], 0)
+
+
 def test_cache_overflow() -> None:
     # Regression test for cache overflow resulting in -1s in encoding
     def get_random_string(length):