Skip to content

Commit cf57d64

Browse files
committed
CLN: make_stat_function for numeric methods in core/generic.py
1 parent e944d01 commit cf57d64

File tree

4 files changed

+58
-146
lines changed

4 files changed

+58
-146
lines changed

pandas/core/generic.py

+55-139
Original file line numberDiff line numberDiff line change
@@ -2807,6 +2807,8 @@ def _add_numeric_operations(cls):
28072807
name = cls._constructor_sliced.__name__ if cls._AXIS_LEN > 1 else 'scalar'
28082808
_num_doc = """
28092809
2810+
%(desc)s
2811+
28102812
Parameters
28112813
----------
28122814
axis : """ + axis_descr + """
@@ -2822,7 +2824,7 @@ def _add_numeric_operations(cls):
28222824
28232825
Returns
28242826
-------
2825-
%(outname)s : """ + name + "\n"
2827+
%(outname)s : """ + name + " or " + cls.__name__ + " (if level specified)\n"
28262828

28272829
_cnum_doc = """
28282830
@@ -2837,25 +2839,46 @@ def _add_numeric_operations(cls):
28372839
-------
28382840
%(outname)s : """ + name + "\n"
28392841

2840-
@Substitution(outname='sum')
2841-
@Appender(_num_doc)
2842-
def sum(self, axis=None, skipna=True, level=None, numeric_only=None,
2843-
**kwargs):
2844-
""" Return sum over requested axis """
2842+
def _make_stat_function(name, desc, f):
28452843

2846-
if axis is None:
2847-
axis = self._stat_axis_number
2848-
if level is not None:
2849-
return self._agg_by_level('sum', axis=axis, level=level,
2850-
skipna=skipna)
2851-
return self._reduce(nanops.nansum, axis=axis,
2852-
skipna=skipna, numeric_only=numeric_only)
2853-
cls.sum = sum
2854-
2855-
@Substitution(outname='mad')
2844+
@Substitution(outname=name, desc=desc)
2845+
@Appender(_num_doc)
2846+
def stat_func(self, axis=None, skipna=None, level=None, numeric_only=None,
2847+
**kwargs):
2848+
if skipna is None:
2849+
skipna = True
2850+
if axis is None:
2851+
axis = self._stat_axis_number
2852+
if level is not None:
2853+
return self._agg_by_level(name, axis=axis, level=level,
2854+
skipna=skipna)
2855+
return self._reduce(f, axis=axis,
2856+
skipna=skipna, numeric_only=numeric_only)
2857+
stat_func.__name__ = name
2858+
return stat_func
2859+
2860+
cls.sum = _make_stat_function('sum',"Return the sum of the values for the requested axis", nanops.nansum)
2861+
cls.mean = _make_stat_function('mean',"Return the mean of the values for the requested axis", nanops.nanmean)
2862+
cls.skew = _make_stat_function('skew',"Return unbiased skew over requested axis\nNormalized by N-1", nanops.nanskew)
2863+
cls.kurt = _make_stat_function('kurt',"Return unbiased kurtosis over requested axis\nNormalized by N-1", nanops.nankurt)
2864+
cls.kurtosis = cls.kurt
2865+
cls.prod = _make_stat_function('prod',"Return the product of the values for the requested axis", nanops.nanprod)
2866+
cls.product = cls.prod
2867+
cls.median = _make_stat_function('median',"Return the median of the values for the requested axis", nanops.nanmedian)
2868+
cls.max = _make_stat_function('max',"""
2869+
This method returns the maximum of the values in the object. If you
2870+
want the *index* of the maximum, use ``idxmax``. This is the
2871+
equivalent of the ``numpy.ndarray`` method ``argmax``.""", nanops.nanmax)
2872+
cls.min = _make_stat_function('min',"""
2873+
This method returns the minimum of the values in the object. If you
2874+
want the *index* of the minimum, use ``idxmin``. This is the
2875+
equivalent of the ``numpy.ndarray`` method ``argmin``.""", nanops.nanmin)
2876+
2877+
@Substitution(outname='mad', desc="Return the mean absolute deviation of the values for the requested axis")
28562878
@Appender(_num_doc)
2857-
def mad(self, axis=None, skipna=True, level=None, **kwargs):
2858-
""" Return the mean absolute deviation of the values for the requested axis """
2879+
def mad(self, axis=None, skipna=None, level=None, **kwargs):
2880+
if skipna is None:
2881+
skipna = True
28592882
if axis is None:
28602883
axis = self._stat_axis_number
28612884
if level is not None:
@@ -2870,27 +2893,11 @@ def mad(self, axis=None, skipna=True, level=None, **kwargs):
28702893
return np.abs(demeaned).mean(axis=axis, skipna=skipna)
28712894
cls.mad = mad
28722895

2873-
@Substitution(outname='mean')
2896+
@Substitution(outname='variance',desc="Return unbiased variance over requested axis\nNormalized by N-1")
28742897
@Appender(_num_doc)
2875-
def mean(self, axis=None, skipna=True, level=None, numeric_only=None, **kwargs):
2876-
""" Return mean over requested axis """
2877-
2878-
if axis is None:
2879-
axis = self._stat_axis_number
2880-
if level is not None:
2881-
return self._agg_by_level('mean', axis=axis, level=level,
2882-
skipna=skipna)
2883-
return self._reduce(nanops.nanmean, axis=axis,
2884-
skipna=skipna, numeric_only=numeric_only)
2885-
cls.mean = mean
2886-
2887-
@Substitution(outname='variance')
2888-
@Appender(_num_doc)
2889-
def var(self, axis=None, skipna=True, level=None, ddof=1, **kwargs):
2890-
"""
2891-
Return unbiased variance over requested axis
2892-
Normalized by N-1 (unbiased estimator).
2893-
"""
2898+
def var(self, axis=None, skipna=None, level=None, ddof=1, **kwargs):
2899+
if skipna is None:
2900+
skipna = True
28942901
if axis is None:
28952902
axis = self._stat_axis_number
28962903
if level is not None:
@@ -2900,13 +2907,11 @@ def var(self, axis=None, skipna=True, level=None, ddof=1, **kwargs):
29002907
return self._reduce(nanops.nanvar, axis=axis, skipna=skipna, ddof=ddof)
29012908
cls.var = var
29022909

2903-
@Substitution(outname='stdev')
2910+
@Substitution(outname='stdev',desc="Return unbiased standard deviation over requested axis\nNormalized by N-1")
29042911
@Appender(_num_doc)
2905-
def std(self, axis=None, skipna=True, level=None, ddof=1, **kwargs):
2906-
"""
2907-
Return unbiased standard deviation over requested axis
2908-
Normalized by N-1 (unbiased estimator).
2909-
"""
2912+
def std(self, axis=None, skipna=None, level=None, ddof=1, **kwargs):
2913+
if skipna is None:
2914+
skipna = True
29102915
if axis is None:
29112916
axis = self._stat_axis_number
29122917
if level is not None:
@@ -2918,105 +2923,14 @@ def std(self, axis=None, skipna=True, level=None, ddof=1, **kwargs):
29182923
return np.sqrt(result)
29192924
cls.std = std
29202925

2921-
@Substitution(outname='skew')
2922-
@Appender(_num_doc)
2923-
def skew(self, axis=None, skipna=True, level=None, **wwargs):
2924-
"""
2925-
Return unbiased standard skewness over requested axis
2926-
Normalized by N-1 (unbiased estimator).
2927-
"""
2928-
if axis is None:
2929-
axis = self._stat_axis_number
2930-
if level is not None:
2931-
return self._agg_by_level('skew', axis=axis, level=level,
2932-
skipna=skipna)
2933-
return self._reduce(nanops.nanskew, axis=axis, skipna=skipna)
2934-
cls.skew = skew
2935-
2936-
@Substitution(outname='kurt')
2937-
@Appender(_num_doc)
2938-
def kurt(self, axis=None, skipna=True, level=None, **kwargs):
2939-
"""
2940-
Return unbiased standard kurtosis over requested axis
2941-
Normalized by N-1 (unbiased estimator).
2942-
"""
2943-
if axis is None:
2944-
axis = self._stat_axis_number
2945-
if level is not None:
2946-
return self._agg_by_level('kurt', axis=axis, level=level,
2947-
skipna=skipna)
2948-
return self._reduce(nanops.nankurt, axis=axis, skipna=skipna,
2949-
numeric_only=None)
2950-
cls.kurt = kurt
2951-
2952-
@Substitution(outname='prod')
2953-
@Appender(_num_doc)
2954-
def prod(self, axis=None, skipna=True, level=None, **kwargs):
2955-
"""
2956-
Return product of the values over requested axis
2957-
"""
2958-
if axis is None:
2959-
axis = self._stat_axis_number
2960-
if level is not None:
2961-
return self._agg_by_level('prod', axis=axis, level=level,
2962-
skipna=skipna)
2963-
return self._reduce(nanops.nanprod, axis=axis, skipna=skipna)
2964-
cls.prod = prod
2965-
cls.product = prod
2966-
2967-
@Substitution(outname='compounded')
2926+
@Substitution(outname='compounded',desc="Return the compound percentage of the values for the requested axis")
29682927
@Appender(_num_doc)
2969-
def compound(self, axis=None, skipna=True, level=None, **kwargs):
2970-
""" return the compound percentage of the values for the requested axis """
2928+
def compound(self, axis=None, skipna=None, level=None, **kwargs):
2929+
if skipna is None:
2930+
skipna = True
29712931
return (1 + self).prod(axis=axis, skipna=skipna, level=level) - 1
29722932
cls.compound = compound
29732933

2974-
@Substitution(outname='median')
2975-
@Appender(_num_doc)
2976-
def median(self, axis=None, skipna=True, level=None, **kwargs):
2977-
"""
2978-
Return median of the values over requested axis
2979-
"""
2980-
if axis is None:
2981-
axis = self._stat_axis_number
2982-
if level is not None:
2983-
return self._agg_by_level('median', axis=axis, level=level,
2984-
skipna=skipna)
2985-
return self._reduce(nanops.nanmedian, axis=axis, skipna=skipna)
2986-
cls.median = median
2987-
2988-
@Substitution(outname='maximum')
2989-
@Appender(_num_doc)
2990-
def max(self, axis=None, skipna=True, level=None, **kwargs):
2991-
"""
2992-
This method returns the maximum of the values in the objec. If you
2993-
want the *index* of the maximum, use ``idxmax``. This is the
2994-
equivalent of the ``numpy.ndarray`` method ``argmax``.
2995-
"""
2996-
if axis is None:
2997-
axis = self._stat_axis_number
2998-
if level is not None:
2999-
return self._agg_by_level('max', axis=axis, level=level,
3000-
skipna=skipna)
3001-
return self._reduce(nanops.nanmax, axis=axis, skipna=skipna)
3002-
cls.max = max
3003-
3004-
@Substitution(outname='minimum')
3005-
@Appender(_num_doc)
3006-
def min(self, axis=None, skipna=True, level=None, **kwargs):
3007-
"""
3008-
This method returns the minimum of the values in the object. If you
3009-
want the *index* of the minimum, use ``idxmin``. This is the
3010-
equivalent of the ``numpy.ndarray`` method ``argmin``.
3011-
"""
3012-
if axis is None:
3013-
axis = self._stat_axis_number
3014-
if level is not None:
3015-
return self._agg_by_level('min', axis=axis, level=level,
3016-
skipna=skipna)
3017-
return self._reduce(nanops.nanmin, axis=axis, skipna=skipna)
3018-
cls.min = min
3019-
30202934
def _make_cum_function(name, accum_func, mask_a, mask_b):
30212935

30222936
@Substitution(outname=name)
@@ -3041,6 +2955,8 @@ def func(self, axis=None, dtype=None, out=None, skipna=True, **kwargs):
30412955
d = self._construct_axes_dict()
30422956
d['copy'] = False
30432957
return self._constructor(result, **d)._propogate_attributes(self)
2958+
2959+
func.__name__ = name
30442960
return func
30452961

30462962

pandas/tests/test_frame.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
map, zip, range, long, lrange, lmap, lzip,
1818
OrderedDict, cPickle as pickle, u, StringIO
1919
)
20-
from pandas import compat
20+
from pandas import compat, _np_version_under1p7
2121

2222
from numpy import random, nan
2323
from numpy.random import randn, rand

pandas/tests/test_generic.py

+1-5
Original file line numberDiff line numberDiff line change
@@ -163,16 +163,12 @@ def test_numpy_1_7_compat_numeric_methods(self):
163163
# numpy in 1.7 tries to pass addtional arguments to pandas functions
164164

165165
o = self._construct(shape=4)
166-
for op in ['min','max','max','var','std','prod','sum',
166+
for op in ['min','max','max','var','std','prod','sum','cumsum','cumprod',
167167
'median','skew','kurt','compound','cummax','cummin','all','any']:
168168
f = getattr(np,op,None)
169169
if f is not None:
170170
f(o)
171171

172-
# numpy broken methods, since these are not passed by keywords, they
173-
# won't work
174-
#'cumsum','cumprod',
175-
176172
class TestSeries(unittest.TestCase, Generic):
177173
_typ = Series
178174
_comparator = lambda self, x, y: assert_series_equal(x,y)

pandas/tests/test_groupby.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from pandas.compat import(
1919
range, long, lrange, StringIO, lmap, lzip, map, zip, builtins, OrderedDict
2020
)
21-
from pandas import compat
21+
from pandas import compat, _np_version_under1p7
2222
from pandas.core.panel import Panel
2323
from pandas.tools.merge import concat
2424
from collections import defaultdict

0 commit comments

Comments
 (0)