Skip to content

Commit e944d01

Browse files
committed
CLN: refactor cum methods to core/generic.py
1 parent 8fa5b03 commit e944d01

File tree

3 files changed

+46
-257
lines changed

3 files changed

+46
-257
lines changed

doc/source/release.rst

+3-1
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,9 @@ See :ref:`Internal Refactoring<whatsnew_0130.refactoring>`
349349
- Complex compat for ``Series`` with ``ndarray``. (:issue:`4819`)
350350
- Removed unnecessary ``rwproperty`` from codebase in favor of builtin property. (:issue:`4843`)
351351
- Refactor object level numeric methods (mean/sum/min/max...) from object level modules to
352-
``core/generic.py``(:issue:`4435`)
352+
``core/generic.py``(:issue:`4435`).
353+
- Refactor cum objects to core/generic.py (:issue:`4435`), note that these have a more numpy-like
354+
function signature.
353355
354356
.. _release.bug_fixes-0.13.0:
355357

pandas/core/generic.py

+43-138
Original file line numberDiff line numberDiff line change
@@ -2816,6 +2816,22 @@ def _add_numeric_operations(cls):
28162816
level : int, default None
28172817
If the axis is a MultiIndex (hierarchical), count along a
28182818
particular level, collapsing into a """ + name + """
2819+
numeric_only : boolean, default None
2820+
Include only float, int, boolean data. If None, will attempt to use
2821+
everything, then use only numeric data
2822+
2823+
Returns
2824+
-------
2825+
%(outname)s : """ + name + "\n"
2826+
2827+
_cnum_doc = """
2828+
2829+
Parameters
2830+
----------
2831+
axis : """ + axis_descr + """
2832+
skipna : boolean, default True
2833+
Exclude NA/null values. If an entire row/column is NA, the result
2834+
will be NA
28192835
28202836
Returns
28212837
-------
@@ -3001,148 +3017,37 @@ def min(self, axis=None, skipna=True, level=None, **kwargs):
30013017
return self._reduce(nanops.nanmin, axis=axis, skipna=skipna)
30023018
cls.min = min
30033019

3004-
def cumsum(self, axis=None, skipna=True, **kwargs):
3005-
"""
3006-
Return DataFrame of cumulative sums over requested axis.
3007-
3008-
Parameters
3009-
----------
3010-
axis : {0, 1}
3011-
0 for row-wise, 1 for column-wise
3012-
skipna : boolean, default True
3013-
Exclude NA/null values. If an entire row/column is NA, the result
3014-
will be NA
3015-
3016-
Returns
3017-
-------
3018-
y : DataFrame
3019-
"""
3020-
if axis is None:
3021-
axis = self._stat_axis_number
3022-
else:
3023-
axis = self._get_axis_number(axis)
3024-
3025-
y = _values_from_object(self).copy()
3026-
if not issubclass(y.dtype.type, np.integer):
3027-
mask = np.isnan(_values_from_object(self))
3028-
3029-
if skipna:
3030-
np.putmask(y, mask, 0.)
3031-
3032-
result = y.cumsum(axis)
3033-
3034-
if skipna:
3035-
np.putmask(result, mask, np.nan)
3036-
else:
3037-
result = y.cumsum(axis)
3038-
return self._wrap_array(result, self.axes, copy=False)
3039-
3040-
def cumprod(self, axis=None, skipna=True, **kwargs):
3041-
"""
3042-
Return cumulative product over requested axis as DataFrame
3043-
3044-
Parameters
3045-
----------
3046-
axis : {0, 1}
3047-
0 for row-wise, 1 for column-wise
3048-
skipna : boolean, default True
3049-
Exclude NA/null values. If an entire row/column is NA, the result
3050-
will be NA
3051-
3052-
Returns
3053-
-------
3054-
y : DataFrame
3055-
"""
3056-
if axis is None:
3057-
axis = self._stat_axis_number
3058-
else:
3059-
axis = self._get_axis_number(axis)
3060-
3061-
y = _values_from_object(self).copy()
3062-
if not issubclass(y.dtype.type, np.integer):
3063-
mask = np.isnan(_values_from_object(self))
3064-
3065-
if skipna:
3066-
np.putmask(y, mask, 1.)
3067-
result = y.cumprod(axis)
3068-
3069-
if skipna:
3070-
np.putmask(result, mask, np.nan)
3071-
else:
3072-
result = y.cumprod(axis)
3073-
return self._wrap_array(result, self.axes, copy=False)
3074-
3075-
def cummax(self, axis=None, skipna=True, **kwargs):
3076-
"""
3077-
Return DataFrame of cumulative max over requested axis.
3078-
3079-
Parameters
3080-
----------
3081-
axis : {0, 1}
3082-
0 for row-wise, 1 for column-wise
3083-
skipna : boolean, default True
3084-
Exclude NA/null values. If an entire row/column is NA, the result
3085-
will be NA
3086-
3087-
Returns
3088-
-------
3089-
y : DataFrame
3090-
"""
3091-
if axis is None:
3092-
axis = self._stat_axis_number
3093-
else:
3094-
axis = self._get_axis_number(axis)
3095-
3096-
y = _values_from_object(self).copy()
3097-
if not issubclass(y.dtype.type, np.integer):
3098-
mask = np.isnan(_values_from_object(self))
3020+
def _make_cum_function(name, accum_func, mask_a, mask_b):
30993021

3100-
if skipna:
3101-
np.putmask(y, mask, -np.inf)
3102-
3103-
result = np.maximum.accumulate(y, axis)
3104-
3105-
if skipna:
3106-
np.putmask(result, mask, np.nan)
3107-
else:
3108-
result = np.maximum.accumulate(y, axis)
3109-
return self._wrap_array(result, self.axes, copy=False)
3110-
3111-
def cummin(self, axis=None, skipna=True, **kwargs):
3112-
"""
3113-
Return DataFrame of cumulative min over requested axis.
3114-
3115-
Parameters
3116-
----------
3117-
axis : {0, 1}
3118-
0 for row-wise, 1 for column-wise
3119-
skipna : boolean, default True
3120-
Exclude NA/null values. If an entire row/column is NA, the result
3121-
will be NA
3122-
3123-
Returns
3124-
-------
3125-
y : DataFrame
3126-
"""
3127-
if axis is None:
3128-
axis = self._stat_axis_number
3129-
else:
3130-
axis = self._get_axis_number(axis)
3131-
3132-
y = _values_from_object(self).copy()
3133-
if not issubclass(y.dtype.type, np.integer):
3134-
mask = np.isnan(_values_from_object(self))
3022+
@Substitution(outname=name)
3023+
@Appender("Return cumulative {0} over requested axis.".format(name) + _cnum_doc)
3024+
def func(self, axis=None, dtype=None, out=None, skipna=True, **kwargs):
3025+
if axis is None:
3026+
axis = self._stat_axis_number
3027+
else:
3028+
axis = self._get_axis_number(axis)
3029+
3030+
y = _values_from_object(self).copy()
3031+
if not issubclass(y.dtype.type, (np.integer,np.bool_)):
3032+
mask = isnull(self)
3033+
if skipna:
3034+
np.putmask(y, mask, mask_a)
3035+
result = accum_func(y, axis)
3036+
if skipna:
3037+
np.putmask(result, mask, mask_b)
3038+
else:
3039+
result = accum_func(y, axis)
31353040

3136-
if skipna:
3137-
np.putmask(y, mask, np.inf)
3041+
d = self._construct_axes_dict()
3042+
d['copy'] = False
3043+
return self._constructor(result, **d)._propogate_attributes(self)
3044+
return func
31383045

3139-
result = np.minimum.accumulate(y, axis)
31403046

3141-
if skipna:
3142-
np.putmask(result, mask, np.nan)
3143-
else:
3144-
result = np.minimum.accumulate(y, axis)
3145-
return self._wrap_array(result, self.axes, copy=False)
3047+
cls.cummin = _make_cum_function('min', lambda y, axis: np.minimum.accumulate(y, axis), np.inf, np.nan)
3048+
cls.cumsum = _make_cum_function('sum', lambda y, axis: y.cumsum(axis), 0., np.nan)
3049+
cls.cumprod = _make_cum_function('prod', lambda y, axis: y.cumprod(axis), 1., np.nan)
3050+
cls.cummax = _make_cum_function('max', lambda y, axis: np.maximum.accumulate(y, axis), -np.inf, np.nan)
31463051

31473052
# install the indexerse
31483053
for _name, _indexer in indexing.get_indexers_list():

pandas/core/series.py

-118
Original file line numberDiff line numberDiff line change
@@ -1216,124 +1216,6 @@ def idxmax(self, axis=None, out=None, skipna=True):
12161216
argmin = idxmin
12171217
argmax = idxmax
12181218

1219-
def cumsum(self, axis=0, dtype=None, out=None, skipna=True):
1220-
"""
1221-
Cumulative sum of values. Preserves locations of NaN values
1222-
1223-
Extra parameters are to preserve ndarray interface.
1224-
1225-
Parameters
1226-
----------
1227-
skipna : boolean, default True
1228-
Exclude NA/null values
1229-
1230-
Returns
1231-
-------
1232-
cumsum : Series
1233-
"""
1234-
arr = _values_from_object(self).copy()
1235-
1236-
do_mask = skipna and not issubclass(self.dtype.type,
1237-
(np.integer, np.bool_))
1238-
if do_mask:
1239-
mask = isnull(arr)
1240-
np.putmask(arr, mask, 0.)
1241-
1242-
result = arr.cumsum()
1243-
1244-
if do_mask:
1245-
np.putmask(result, mask, pa.NA)
1246-
1247-
return self._constructor(result, index=self.index, name=self.name)
1248-
1249-
def cumprod(self, axis=0, dtype=None, out=None, skipna=True):
1250-
"""
1251-
Cumulative product of values. Preserves locations of NaN values
1252-
1253-
Extra parameters are to preserve ndarray interface.
1254-
1255-
Parameters
1256-
----------
1257-
skipna : boolean, default True
1258-
Exclude NA/null values
1259-
1260-
Returns
1261-
-------
1262-
cumprod : Series
1263-
"""
1264-
arr = _values_from_object(self).copy()
1265-
1266-
do_mask = skipna and not issubclass(self.dtype.type,
1267-
(np.integer, np.bool_))
1268-
if do_mask:
1269-
mask = isnull(arr)
1270-
np.putmask(arr, mask, 1.)
1271-
1272-
result = arr.cumprod()
1273-
1274-
if do_mask:
1275-
np.putmask(result, mask, pa.NA)
1276-
1277-
return self._constructor(result, index=self.index, name=self.name)
1278-
1279-
def cummax(self, axis=0, dtype=None, out=None, skipna=True):
1280-
"""
1281-
Cumulative max of values. Preserves locations of NaN values
1282-
1283-
Extra parameters are to preserve ndarray interface.
1284-
1285-
Parameters
1286-
----------
1287-
skipna : boolean, default True
1288-
Exclude NA/null values
1289-
1290-
Returns
1291-
-------
1292-
cummax : Series
1293-
"""
1294-
arr = _values_from_object(self).copy()
1295-
1296-
do_mask = skipna and not issubclass(self.dtype.type, np.integer)
1297-
if do_mask:
1298-
mask = isnull(arr)
1299-
np.putmask(arr, mask, -np.inf)
1300-
1301-
result = np.maximum.accumulate(arr)
1302-
1303-
if do_mask:
1304-
np.putmask(result, mask, pa.NA)
1305-
1306-
return self._constructor(result, index=self.index, name=self.name)
1307-
1308-
def cummin(self, axis=0, dtype=None, out=None, skipna=True):
1309-
"""
1310-
Cumulative min of values. Preserves locations of NaN values
1311-
1312-
Extra parameters are to preserve ndarray interface.
1313-
1314-
Parameters
1315-
----------
1316-
skipna : boolean, default True
1317-
Exclude NA/null values
1318-
1319-
Returns
1320-
-------
1321-
cummin : Series
1322-
"""
1323-
arr = _values_from_object(self).copy()
1324-
1325-
do_mask = skipna and not issubclass(self.dtype.type, np.integer)
1326-
if do_mask:
1327-
mask = isnull(arr)
1328-
np.putmask(arr, mask, np.inf)
1329-
1330-
result = np.minimum.accumulate(arr)
1331-
1332-
if do_mask:
1333-
np.putmask(result, mask, pa.NA)
1334-
1335-
return self._constructor(result, index=self.index, name=self.name)
1336-
13371219
@Appender(pa.Array.round.__doc__)
13381220
def round(self, decimals=0, out=None):
13391221
"""

0 commit comments

Comments
 (0)