Repository: pandas-dev/pandas

Issue:
ENH: window functions need to exclude nuiscance columns
xref example in : #13327

```
In [4]: df = DataFrame({'A' : pd.date_range('20130101',periods=3),'B' : range(3)})

In [5]: df
Out[5]: 
           A  B
0 2013-01-01  0
1 2013-01-02  1
2 2013-01-03  2
```

This is a supported op

```
In [7]: df.rolling(window=2).count()
Out[7]: 
     A    B
0  1.0  1.0
1  2.0  2.0
2  2.0  2.0
```

This works

```
In [9]: df.rolling(window=2).B.sum()
Out[9]: 
0    NaN
1    1.0
2    3.0
Name: B, dtype: float64
```

```
df.rolling(window=2).sum()
```

should work (but excluded `A`) from the results.



Discussion:
xref #4964 


Resolving patch:
diff --git a/pandas/core/window.py b/pandas/core/window.py
--- a/pandas/core/window.py
+++ b/pandas/core/window.py
@@ -22,7 +22,7 @@
     ABCDataFrame, ABCDateOffset, ABCDatetimeIndex, ABCPeriodIndex, ABCSeries,
     ABCTimedeltaIndex)
 
-from pandas.core.base import PandasObject, SelectionMixin
+from pandas.core.base import DataError, PandasObject, SelectionMixin
 import pandas.core.common as com
 from pandas.core.generic import _shared_docs
 from pandas.core.groupby.base import GroupByMixin
@@ -243,7 +243,7 @@ def _wrap_result(self, result, block=None, obj=None):
             return type(obj)(result, index=index, columns=block.columns)
         return result
 
-    def _wrap_results(self, results, blocks, obj):
+    def _wrap_results(self, results, blocks, obj, exclude=None):
         """
         Wrap the results.
 
@@ -252,6 +252,7 @@ def _wrap_results(self, results, blocks, obj):
         results : list of ndarrays
         blocks : list of blocks
         obj : conformed data (may be resampled)
+        exclude: list of columns to exclude, default to None
         """
 
         from pandas import Series, concat
@@ -285,6 +286,13 @@ def _wrap_results(self, results, blocks, obj):
                     indexer = columns.get_indexer(selection.tolist() + [name])
                     columns = columns.take(sorted(indexer))
 
+        # exclude nuisance columns so that they are not reindexed
+        if exclude is not None and exclude:
+            columns = [c for c in columns if c not in exclude]
+
+            if not columns:
+                raise DataError('No numeric types to aggregate')
+
         if not len(final):
             return obj.astype('float64')
         return concat(final, axis=1).reindex(columns=columns, copy=False)
@@ -672,13 +680,21 @@ def _apply_window(self, mean=True, **kwargs):
         center = self.center
 
         blocks, obj, index = self._create_blocks()
+        block_list = list(blocks)
+
         results = []
-        for b in blocks:
+        exclude = []
+        for i, b in enumerate(blocks):
             try:
                 values = self._prep_values(b.values)
-            except TypeError:
-                results.append(b.values.copy())
-                continue
+
+            except (TypeError, NotImplementedError):
+                if isinstance(obj, ABCDataFrame):
+                    exclude.extend(b.columns)
+                    del block_list[i]
+                    continue
+                else:
+                    raise DataError('No numeric types to aggregate')
 
             if values.size == 0:
                 results.append(values.copy())
@@ -700,7 +716,7 @@ def f(arg, *args, **kwargs):
                 result = self._center_window(result, window)
             results.append(result)
 
-        return self._wrap_results(results, blocks, obj)
+        return self._wrap_results(results, block_list, obj, exclude)
 
     _agg_see_also_doc = dedent("""
     See Also
@@ -843,10 +859,22 @@ def _apply(self, func, name=None, window=None, center=None,
             check_minp = _use_window
 
         blocks, obj, index = self._create_blocks()
+        block_list = list(blocks)
         index, indexi = self._get_index(index=index)
+
         results = []
-        for b in blocks:
-            values = self._prep_values(b.values)
+        exclude = []
+        for i, b in enumerate(blocks):
+            try:
+                values = self._prep_values(b.values)
+
+            except (TypeError, NotImplementedError):
+                if isinstance(obj, ABCDataFrame):
+                    exclude.extend(b.columns)
+                    del block_list[i]
+                    continue
+                else:
+                    raise DataError('No numeric types to aggregate')
 
             if values.size == 0:
                 results.append(values.copy())
@@ -892,7 +920,7 @@ def calc(x):
 
             results.append(result)
 
-        return self._wrap_results(results, blocks, obj)
+        return self._wrap_results(results, block_list, obj, exclude)
 
 
 class _Rolling_and_Expanding(_Rolling):
@@ -2291,13 +2319,21 @@ def _apply(self, func, **kwargs):
         y : same type as input argument
         """
         blocks, obj, index = self._create_blocks()
+        block_list = list(blocks)
+
         results = []
-        for b in blocks:
+        exclude = []
+        for i, b in enumerate(blocks):
             try:
                 values = self._prep_values(b.values)
-            except TypeError:
-                results.append(b.values.copy())
-                continue
+
+            except (TypeError, NotImplementedError):
+                if isinstance(obj, ABCDataFrame):
+                    exclude.extend(b.columns)
+                    del block_list[i]
+                    continue
+                else:
+                    raise DataError('No numeric types to aggregate')
 
             if values.size == 0:
                 results.append(values.copy())
@@ -2316,7 +2352,7 @@ def func(arg):
 
             results.append(np.apply_along_axis(func, self.axis, values))
 
-        return self._wrap_results(results, blocks, obj)
+        return self._wrap_results(results, block_list, obj, exclude)
 
     @Substitution(name='ewm')
     @Appender(_doc_template)


Test patch:
diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py
--- a/pandas/tests/test_window.py
+++ b/pandas/tests/test_window.py
@@ -14,7 +14,7 @@
 import pandas as pd
 from pandas import (
     DataFrame, Index, Series, Timestamp, bdate_range, concat, isna, notna)
-from pandas.core.base import SpecificationError
+from pandas.core.base import DataError, SpecificationError
 from pandas.core.sorting import safe_sort
 import pandas.core.window as rwindow
 import pandas.util.testing as tm
@@ -118,9 +118,11 @@ def tests_skip_nuisance(self):
     def test_skip_sum_object_raises(self):
         df = DataFrame({'A': range(5), 'B': range(5, 10), 'C': 'foo'})
         r = df.rolling(window=3)
-
-        with pytest.raises(TypeError, match='cannot handle this type'):
-            r.sum()
+        result = r.sum()
+        expected = DataFrame({'A': [np.nan, np.nan, 3, 6, 9],
+                              'B': [np.nan, np.nan, 18, 21, 24]},
+                             columns=list('AB'))
+        tm.assert_frame_equal(result, expected)
 
     def test_agg(self):
         df = DataFrame({'A': range(5), 'B': range(0, 10, 2)})
@@ -1069,15 +1071,12 @@ class DatetimeLike(Dtype):
     def check_dtypes(self, f, f_name, d, d_name, exp):
 
         roll = d.rolling(window=self.window)
-
         if f_name == 'count':
             result = f(roll)
             tm.assert_almost_equal(result, exp)
 
         else:
-
-            # other methods not Implemented ATM
-            with pytest.raises(NotImplementedError):
+            with pytest.raises(DataError):
                 f(roll)