Repository: pandas-dev/pandas

Issue:
DataFrame.asof() fails when some columns are NaN
#### Code Sample, a copy-pastable example if possible

```python
    import pandas as pd
   
    data = """dt,a,b
   2018-02-27 09:01:00,-0.00034052907999999996,
   2018-02-27 09:02:00,-0.00019981724999999998,
   2018-02-27 09:03:00,-0.0009561605,
   2018-02-27 09:04:00,-0.0005727226999999999,
   2018-02-27 09:05:00,-0.0006973449,4.2"""
 
    from io import StringIO
    buff = StringIO(data)
    df = pd.read_csv(buff, parse_dates=['dt'])
    df.set_index('dt', drop=True, inplace=True)
   
    print(df.asof(pd.DatetimeIndex(['2018-02-27 09:03:30','2018-02-27 09:04:30'])))

# gives
#                          a   b
#    2018-02-27 09:03:30 NaN NaN
#    2018-02-27 09:04:30 NaN NaN

# but, 
    df['a'].asof(pd.DatetimeIndex(['2018-02-27 09:03:30','2018-02-27 09:04:30']))

# gives
#    2018-02-27 09:03:30   -0.000956
#    2018-02-27 09:04:30   -0.000573
#    Name: a, dtype: float64
```
#### Problem description

NaN's in column 'b' should not affect asof() on column 'a'

#### Expected Output
```
                         a   b
    2018-02-27 09:03:30 -0.000956 NaN
    2018-02-27 09:04:30 -0.000573 NaN
```

#### Output of ``pd.show_versions()``

<details>

pandas: 0.22.0
numpy 1.14.2

</details>



Discussion:
yeah this is correct.

```
In [7]: df.apply(lambda x: x.asof(pd.DatetimeIndex(['2018-02-27 09:03:30','2018-02-27 09:04:30'])))
Out[7]: 
                            a   b
2018-02-27 09:03:30 -0.000956 NaN
2018-02-27 09:04:30 -0.000573 NaN
```
welcome for you to have a look see and PR even better!
Ok @jreback will try and take a look over the weekend. Also thanks for everything u do for pandas/open source. Its very much appreciated :)
@jreback I also think this behavior is weird, but is it really a bug? In docs,
> The last **row** without any NaN is taken

http://pandas.pydata.org/pandas-docs/version/0.19.0/generated/pandas.DataFrame.asof.html
It doesn't seem like a bug. Docs specify that unless **subset** is specified, all the columns are being considered. 

> (or the last row without NaN considering only the subset of columns in the case of a DataFrame

However, the phrasing might not be obvious, I'll try to improve the docs.

Resolving patch:
diff --git a/pandas/core/generic.py b/pandas/core/generic.py
--- a/pandas/core/generic.py
+++ b/pandas/core/generic.py
@@ -6495,40 +6495,98 @@ def interpolate(self, method='linear', axis=0, limit=None, inplace=False,
 
     def asof(self, where, subset=None):
         """
-        The last row without any NaN is taken (or the last row without
-        NaN considering only the subset of columns in the case of a DataFrame)
+        Return the last row(s) without any `NaN`s before `where`.
+
+        The last row (for each element in `where`, if list) without any
+        `NaN` is taken.
+        In case of a :class:`~pandas.DataFrame`, the last row without `NaN`
+        considering only the subset of columns (if not `None`)
 
         .. versionadded:: 0.19.0 For DataFrame
 
-        If there is no good value, NaN is returned for a Series
+        If there is no good value, `NaN` is returned for a Series or
         a Series of NaN values for a DataFrame
 
         Parameters
         ----------
-        where : date or array of dates
-        subset : string or list of strings, default None
-           if not None use these columns for NaN propagation
+        where : date or array-like of dates
+            Date(s) before which the last row(s) are returned.
+        subset : str or array-like of str, default `None`
+            For DataFrame, if not `None`, only use these columns to
+            check for `NaN`s.
 
         Notes
         -----
-        Dates are assumed to be sorted
-        Raises if this is not the case
+        Dates are assumed to be sorted. Raises if this is not the case.
 
         Returns
         -------
-        where is scalar
-
-          - value or NaN if input is Series
-          - Series if input is DataFrame
+        scalar, Series, or DataFrame
 
-        where is Index: same shape object as input
+           * scalar : when `self` is a Series and `where` is a scalar
+           * Series: when `self` is a Series and `where` is an array-like,
+             or when `self` is a DataFrame and `where` is a scalar
+           * DataFrame : when `self` is a DataFrame and `where` is an
+             array-like
 
         See Also
         --------
-        merge_asof
+        merge_asof : Perform an asof merge. Similar to left join.
 
-        """
+        Examples
+        --------
+        A Series and a scalar `where`.
+
+        >>> s = pd.Series([1, 2, np.nan, 4], index=[10, 20, 30, 40])
+        >>> s
+        10    1.0
+        20    2.0
+        30    NaN
+        40    4.0
+        dtype: float64
+
+        >>> s.asof(20)
+        2.0
 
+        For a sequence `where`, a Series is returned. The first value is
+        ``NaN``, because the first element of `where` is before the first
+        index value.
+
+        >>> s.asof([5, 20])
+        5     NaN
+        20    2.0
+        dtype: float64
+
+        Missing values are not considered. The following is ``2.0``, not
+        ``NaN``, even though ``NaN`` is at the index location for ``30``.
+
+        >>> s.asof(30)
+        2.0
+
+        Take all columns into consideration
+
+        >>> df = pd.DataFrame({'a': [10, 20, 30, 40, 50],
+        ...                    'b': [None, None, None, None, 500]},
+        ...                   index=pd.DatetimeIndex(['2018-02-27 09:01:00',
+        ...                                           '2018-02-27 09:02:00',
+        ...                                           '2018-02-27 09:03:00',
+        ...                                           '2018-02-27 09:04:00',
+        ...                                           '2018-02-27 09:05:00']))
+        >>> df.asof(pd.DatetimeIndex(['2018-02-27 09:03:30',
+        ...                           '2018-02-27 09:04:30']))
+                              a   b
+        2018-02-27 09:03:30 NaN NaN
+        2018-02-27 09:04:30 NaN NaN
+
+        Take a single column into consideration
+
+        >>> df.asof(pd.DatetimeIndex(['2018-02-27 09:03:30',
+        ...                           '2018-02-27 09:04:30']),
+        ...         subset=['a'])
+                                 a   b
+        2018-02-27 09:03:30   30.0 NaN
+        2018-02-27 09:04:30   40.0 NaN
+        """
         if isinstance(where, compat.string_types):
             from pandas import to_datetime
             where = to_datetime(where)


Test patch: