def asof(self, where, subset=None):
    "\n        Return the last row(s) without any NaNs before `where`.\n\n        The last row (for each element in `where`, if list) without any\n        NaN is taken.\n        In case of a :class:`~pandas.DataFrame`, the last row without NaN\n        considering only the subset of columns (if not `None`)\n\n        .. versionadded:: 0.19.0 For DataFrame\n\n        If there is no good value, NaN is returned for a Series or\n        a Series of NaN values for a DataFrame\n\n        Parameters\n        ----------\n        where : date or array-like of dates\n            Date(s) before which the last row(s) are returned.\n        subset : str or array-like of str, default `None`\n            For DataFrame, if not `None`, only use these columns to\n            check for NaNs.\n\n        Returns\n        -------\n        scalar, Series, or DataFrame\n\n            The return can be:\n\n            * scalar : when `self` is a Series and `where` is a scalar\n            * Series: when `self` is a Series and `where` is an array-like,\n              or when `self` is a DataFrame and `where` is a scalar\n            * DataFrame : when `self` is a DataFrame and `where` is an\n              array-like\n\n            Return scalar, Series, or DataFrame.\n\n        See Also\n        --------\n        merge_asof : Perform an asof merge. Similar to left join.\n\n        Notes\n        -----\n        Dates are assumed to be sorted. Raises if this is not the case.\n\n        Examples\n        --------\n        A Series and a scalar `where`.\n\n        >>> s = pd.Series([1, 2, np.nan, 4], index=[10, 20, 30, 40])\n        >>> s\n        10    1.0\n        20    2.0\n        30    NaN\n        40    4.0\n        dtype: float64\n\n        >>> s.asof(20)\n        2.0\n\n        For a sequence `where`, a Series is returned. The first value is\n        NaN, because the first element of `where` is before the first\n        index value.\n\n        >>> s.asof([5, 20])\n        5     NaN\n        20    2.0\n        dtype: float64\n\n        Missing values are not considered. The following is ``2.0``, not\n        NaN, even though NaN is at the index location for ``30``.\n\n        >>> s.asof(30)\n        2.0\n\n        Take all columns into consideration\n\n        >>> df = pd.DataFrame({'a': [10, 20, 30, 40, 50],\n        ...                    'b': [None, None, None, None, 500]},\n        ...                   index=pd.DatetimeIndex(['2018-02-27 09:01:00',\n        ...                                           '2018-02-27 09:02:00',\n        ...                                           '2018-02-27 09:03:00',\n        ...                                           '2018-02-27 09:04:00',\n        ...                                           '2018-02-27 09:05:00']))\n        >>> df.asof(pd.DatetimeIndex(['2018-02-27 09:03:30',\n        ...                           '2018-02-27 09:04:30']))\n                              a   b\n        2018-02-27 09:03:30 NaN NaN\n        2018-02-27 09:04:30 NaN NaN\n\n        Take a single column into consideration\n\n        >>> df.asof(pd.DatetimeIndex(['2018-02-27 09:03:30',\n        ...                           '2018-02-27 09:04:30']),\n        ...         subset=['a'])\n                                 a   b\n        2018-02-27 09:03:30   30.0 NaN\n        2018-02-27 09:04:30   40.0 NaN\n        "
    if isinstance(where, compat.string_types):
        from pandas import to_datetime
        where = to_datetime(where)
    if (not self.index.is_monotonic):
        raise ValueError('asof requires a sorted index')
    is_series = isinstance(self, ABCSeries)
    if is_series:
        if (subset is not None):
            raise ValueError('subset is not valid for Series')
    elif (self.ndim > 2):
        raise NotImplementedError('asof is not implemented for {type}'.format(type=type(self)))
    else:
        if (subset is None):
            subset = self.columns
        if (not is_list_like(subset)):
            subset = [subset]
    is_list = is_list_like(where)
    if (not is_list):
        start = self.index[0]
        if isinstance(self.index, PeriodIndex):
            where = Period(where, freq=self.index.freq).ordinal
            start = start.ordinal
        if (where < start):
            if (not is_series):
                from pandas import Series
                return Series(index=self.columns, name=where)
            return np.nan
        if is_series:
            loc = self.index.searchsorted(where, side='right')
            if (loc > 0):
                loc -= 1
            values = self._values
            while ((loc > 0) and isna(values[loc])):
                loc -= 1
            return values[loc]
    if (not isinstance(where, Index)):
        where = (Index(where) if is_list else Index([where]))
    nulls = (self.isna() if is_series else self[subset].isna().any(1))
    if nulls.all():
        if is_series:
            return self._constructor(np.nan, index=where, name=self.name)
        elif is_list:
            from pandas import DataFrame
            return DataFrame(np.nan, index=where, columns=self.columns)
        else:
            from pandas import Series
            return Series(np.nan, index=self.columns, name=where[0])
    locs = self.index.asof_locs(where, (~ nulls.values))
    missing = (locs == (- 1))
    data = self.take(locs, is_copy=False)
    data.index = where
    data.loc[missing] = np.nan
    return (data if is_list else data.iloc[(- 1)])
Return the last row(s) without any NaNs 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 or
a Series of NaN values for a DataFrame

Parameters
----------
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 NaNs.

Returns
-------
scalar, Series, or DataFrame

    The return can be:

    * 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

    Return scalar, Series, or DataFrame.

See Also
--------
merge_asof : Perform an asof merge. Similar to left join.

Notes
-----
Dates are assumed to be sorted. Raises if this is not the case.

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
def asof(self, where, subset=None):
    "\n        Return the last row(s) without any NaNs before `where`.\n\n        The last row (for each element in `where`, if list) without any\n        NaN is taken.\n        In case of a :class:`~pandas.DataFrame`, the last row without NaN\n        considering only the subset of columns (if not `None`)\n\n        .. versionadded:: 0.19.0 For DataFrame\n\n        If there is no good value, NaN is returned for a Series or\n        a Series of NaN values for a DataFrame\n\n        Parameters\n        ----------\n        where : date or array-like of dates\n            Date(s) before which the last row(s) are returned.\n        subset : str or array-like of str, default `None`\n            For DataFrame, if not `None`, only use these columns to\n            check for NaNs.\n\n        Returns\n        -------\n        scalar, Series, or DataFrame\n\n            The return can be:\n\n            * scalar : when `self` is a Series and `where` is a scalar\n            * Series: when `self` is a Series and `where` is an array-like,\n              or when `self` is a DataFrame and `where` is a scalar\n            * DataFrame : when `self` is a DataFrame and `where` is an\n              array-like\n\n            Return scalar, Series, or DataFrame.\n\n        See Also\n        --------\n        merge_asof : Perform an asof merge. Similar to left join.\n\n        Notes\n        -----\n        Dates are assumed to be sorted. Raises if this is not the case.\n\n        Examples\n        --------\n        A Series and a scalar `where`.\n\n        >>> s = pd.Series([1, 2, np.nan, 4], index=[10, 20, 30, 40])\n        >>> s\n        10    1.0\n        20    2.0\n        30    NaN\n        40    4.0\n        dtype: float64\n\n        >>> s.asof(20)\n        2.0\n\n        For a sequence `where`, a Series is returned. The first value is\n        NaN, because the first element of `where` is before the first\n        index value.\n\n        >>> s.asof([5, 20])\n        5     NaN\n        20    2.0\n        dtype: float64\n\n        Missing values are not considered. The following is ``2.0``, not\n        NaN, even though NaN is at the index location for ``30``.\n\n        >>> s.asof(30)\n        2.0\n\n        Take all columns into consideration\n\n        >>> df = pd.DataFrame({'a': [10, 20, 30, 40, 50],\n        ...                    'b': [None, None, None, None, 500]},\n        ...                   index=pd.DatetimeIndex(['2018-02-27 09:01:00',\n        ...                                           '2018-02-27 09:02:00',\n        ...                                           '2018-02-27 09:03:00',\n        ...                                           '2018-02-27 09:04:00',\n        ...                                           '2018-02-27 09:05:00']))\n        >>> df.asof(pd.DatetimeIndex(['2018-02-27 09:03:30',\n        ...                           '2018-02-27 09:04:30']))\n                              a   b\n        2018-02-27 09:03:30 NaN NaN\n        2018-02-27 09:04:30 NaN NaN\n\n        Take a single column into consideration\n\n        >>> df.asof(pd.DatetimeIndex(['2018-02-27 09:03:30',\n        ...                           '2018-02-27 09:04:30']),\n        ...         subset=['a'])\n                                 a   b\n        2018-02-27 09:03:30   30.0 NaN\n        2018-02-27 09:04:30   40.0 NaN\n        "
    if isinstance(where, compat.string_types):
        from pandas import to_datetime
        where = to_datetime(where)
    if (not self.index.is_monotonic):
        raise ValueError('asof requires a sorted index')
    is_series = isinstance(self, ABCSeries)
    if is_series:
        if (subset is not None):
            raise ValueError('subset is not valid for Series')
    elif (self.ndim > 2):
        raise NotImplementedError('asof is not implemented for {type}'.format(type=type(self)))
    else:
        if (subset is None):
            subset = self.columns
        if (not is_list_like(subset)):
            subset = [subset]
    is_list = is_list_like(where)
    if (not is_list):
        start = self.index[0]
        if isinstance(self.index, PeriodIndex):
            where = Period(where, freq=self.index.freq).ordinal
            start = start.ordinal
        if (where < start):
            if (not is_series):
                from pandas import Series
                return Series(index=self.columns, name=where)
            return np.nan
        if is_series:
            loc = self.index.searchsorted(where, side='right')
            if (loc > 0):
                loc -= 1
            values = self._values
            while ((loc > 0) and isna(values[loc])):
                loc -= 1
            return values[loc]
    if (not isinstance(where, Index)):
        where = (Index(where) if is_list else Index([where]))
    nulls = (self.isna() if is_series else self[subset].isna().any(1))
    if nulls.all():
        if is_series:
            return self._constructor(np.nan, index=where, name=self.name)
        elif is_list:
            from pandas import DataFrame
            return DataFrame(np.nan, index=where, columns=self.columns)
        else:
            from pandas import Series
            return Series(np.nan, index=self.columns, name=where[0])
    locs = self.index.asof_locs(where, (~ nulls.values))
    missing = (locs == (- 1))
    data = self.take(locs, is_copy=False)
    data.index = where
    data.loc[missing] = np.nan
    return (data if is_list else data.iloc[(- 1)])