Repository: pandas-dev/pandas

Issue:
string match returns NaN on non strings
Or just not respecting na flag.

```
In [44]: s = pd.Series(['a', 0, np.nan])

In [45]: s.str.contains('a', na=False)
Out[45]:
0     True
1    False
2    False
dtype: bool

In [46]: s.str.match('a', na=False)
Out[46]:
0    True
1     NaN
2     NaN
dtype: object
```



Discussion:

Resolving patch:
diff --git a/pandas/core/strings.py b/pandas/core/strings.py
--- a/pandas/core/strings.py
+++ b/pandas/core/strings.py
@@ -364,11 +364,11 @@ def str_match(arr, pat, case=True, flags=0, na=np.nan, as_indexer=False):
         # Do this first, to make sure it happens even if the re.compile
         # raises below.
         warnings.warn("In future versions of pandas, match will change to"
-                      " always return a bool indexer.""", UserWarning)
+                      " always return a bool indexer.", UserWarning)
 
     if as_indexer and regex.groups > 0:
         warnings.warn("This pattern has match groups. To actually get the"
-                      " groups, use str.extract.""", UserWarning)
+                      " groups, use str.extract.", UserWarning)
 
     # If not as_indexer and regex.groups == 0, this returns empty lists
     # and is basically useless, so we will not warn.
@@ -384,7 +384,7 @@ def f(x):
         # This is the new behavior of str_match.
         f = lambda x: bool(regex.match(x))
 
-    return _na_map(f, arr)
+    return _na_map(f, arr, na)
 
 
 def str_extract(arr, pat, flags=0):
@@ -887,6 +887,12 @@ def contains(self, pat, case=True, flags=0, na=np.nan, regex=True):
                               na=na, regex=regex)
         return self._wrap_result(result)
 
+    @copy(str_match)
+    def match(self, pat, case=True, flags=0, na=np.nan, as_indexer=False):
+        result = str_match(self.series, pat, case=case, flags=flags,
+                              na=na, as_indexer=as_indexer)
+        return self._wrap_result(result)
+
     @copy(str_replace)
     def replace(self, pat, repl, n=-1, case=True, flags=0):
         result = str_replace(self.series, pat, repl, n=n, case=case,
@@ -951,7 +957,6 @@ def get_dummies(self, sep='|'):
     startswith = _pat_wrapper(str_startswith, na=True)
     endswith = _pat_wrapper(str_endswith, na=True)
     findall = _pat_wrapper(str_findall, flags=True)
-    match = _pat_wrapper(str_match, flags=True)
     extract = _pat_wrapper(str_extract, flags=True)
 
     len = _noarg_wrapper(str_len)


Test patch:
diff --git a/pandas/tests/test_strings.py b/pandas/tests/test_strings.py
--- a/pandas/tests/test_strings.py
+++ b/pandas/tests/test_strings.py
@@ -220,7 +220,7 @@ def test_contains(self):
         # na
         values = Series(['om', 'foo',np.nan])
         res = values.str.contains('foo', na="foo")
-        self.assertEqual (res.ix[2], "foo"        )
+        self.assertEqual (res.ix[2], "foo")
 
     def test_startswith(self):
         values = Series(['om', NA, 'foo_nom', 'nom', 'bar_foo', NA, 'foo'])
@@ -460,6 +460,14 @@ def test_match(self):
         exp = Series([True, NA, False])
         tm.assert_series_equal(result, exp)
 
+        # na GH #6609
+        res = Series(['a', 0, np.nan]).str.match('a', na=False)
+        exp = Series([True, False, False])
+        assert_series_equal(exp, res)
+        res = Series(['a', 0, np.nan]).str.match('a')
+        exp = Series([True, np.nan, np.nan])
+        assert_series_equal(exp, res)
+
     def test_extract(self):
         # Contains tests like those in test_match and some others.