|
16 | 16 | from pandas.util import py3compat
|
17 | 17 | from pandas.util.decorators import deprecate
|
18 | 18 | import pandas.core.common as com
|
| 19 | +import pandas.core.nanops as nanops |
19 | 20 | import pandas._tseries as lib
|
20 | 21 |
|
21 | 22 |
|
@@ -939,6 +940,19 @@ def _array_method(self, func, axis='major', fill_value=None, skipna=True):
|
939 | 940 | result = self._values_aggregate(func, axis, fill_value, skipna=skipna)
|
940 | 941 | return self._wrap_result(result, axis=axis)
|
941 | 942 |
|
| 943 | + def _reduce(self, op, axis=0, skipna=True): |
| 944 | + axis_name = self._get_axis_name(axis) |
| 945 | + axis_number = self._get_axis_number(axis_name) |
| 946 | + f = lambda x: op(x, axis=axis_number, skipna=skipna, copy=True) |
| 947 | + |
| 948 | + result = f(self.values) |
| 949 | + |
| 950 | + index, columns = self._get_plane_axes(axis_name) |
| 951 | + if axis_name != 'items': |
| 952 | + result = result.T |
| 953 | + |
| 954 | + return DataFrame(result, index=index, columns=columns) |
| 955 | + |
942 | 956 | def _wrap_result(self, result, axis):
|
943 | 957 | axis = self._get_axis_name(axis)
|
944 | 958 | index, columns = self._get_plane_axes(axis)
|
@@ -969,90 +983,43 @@ def count(self, axis='major'):
|
969 | 983 | return self._wrap_result(result, axis)
|
970 | 984 |
|
971 | 985 | def sum(self, axis='major', skipna=True):
|
972 |
| - return self._array_method(np.sum, axis=axis, fill_value=0, |
973 |
| - skipna=skipna) |
974 |
| - |
| 986 | + return self._reduce(nanops.nansum, axis=axis, skipna=skipna) |
975 | 987 | _add_docs(sum, 'sum', 'sum')
|
976 | 988 |
|
977 | 989 | def mean(self, axis='major', skipna=True):
|
978 |
| - the_sum = self.sum(axis=axis, skipna=skipna) |
979 |
| - the_count = self.count(axis=axis) |
980 |
| - return the_sum / the_count |
981 |
| - |
| 990 | + return self._reduce(nanops.nanmean, axis=axis, skipna=skipna) |
982 | 991 | _add_docs(mean, 'mean', 'mean')
|
983 | 992 |
|
984 | 993 | def var(self, axis='major', skipna=True):
|
985 |
| - i = self._get_axis_number(axis) |
986 |
| - y = np.array(self.values) |
987 |
| - mask = np.isnan(y) |
988 |
| - |
989 |
| - count = (-mask).sum(axis=i).astype(float) |
990 |
| - |
991 |
| - if skipna: |
992 |
| - y[mask] = 0 |
993 |
| - |
994 |
| - X = y.sum(axis=i) |
995 |
| - XX = (y ** 2).sum(axis=i) |
996 |
| - |
997 |
| - theVar = (XX - X**2 / count) / (count - 1) |
998 |
| - |
999 |
| - return self._wrap_result(theVar, axis) |
1000 |
| - |
| 994 | + return self._reduce(nanops.nanvar, axis=axis, skipna=skipna) |
1001 | 995 | _add_docs(var, 'unbiased variance', 'variance')
|
1002 | 996 |
|
1003 | 997 | def std(self, axis='major', skipna=True):
|
1004 | 998 | return self.var(axis=axis, skipna=skipna).apply(np.sqrt)
|
1005 |
| - |
1006 | 999 | _add_docs(std, 'unbiased standard deviation', 'stdev')
|
1007 | 1000 |
|
1008 |
| - def prod(self, axis='major', skipna=True): |
1009 |
| - return self._array_method(np.prod, axis=axis, fill_value=1, |
1010 |
| - skipna=skipna) |
| 1001 | + def skew(self, axis='major', skipna=True): |
| 1002 | + return self._reduce(nanops.nanskew, axis=axis, skipna=skipna) |
| 1003 | + _add_docs(std, 'unbiased skewness', 'skew') |
1011 | 1004 |
|
| 1005 | + def prod(self, axis='major', skipna=True): |
| 1006 | + return self._reduce(nanops.nanprod, axis=axis, skipna=skipna) |
1012 | 1007 | _add_docs(prod, 'product', 'prod')
|
1013 | 1008 |
|
1014 | 1009 | def compound(self, axis='major', skipna=True):
|
1015 | 1010 | return (1 + self).prod(axis=axis, skipna=skipna) - 1
|
1016 |
| - |
1017 | 1011 | _add_docs(compound, 'compounded percentage', 'compounded')
|
1018 | 1012 |
|
1019 | 1013 | def median(self, axis='major', skipna=True):
|
1020 |
| - def f(arr): |
1021 |
| - mask = com.notnull(arr) |
1022 |
| - if skipna: |
1023 |
| - return lib.median(arr[mask]) |
1024 |
| - else: |
1025 |
| - if not mask.all(): |
1026 |
| - return np.nan |
1027 |
| - return lib.median(arr) |
1028 |
| - return self.apply(f, axis=axis) |
1029 |
| - |
| 1014 | + return self._reduce(nanops.nanmedian, axis=axis, skipna=skipna) |
1030 | 1015 | _add_docs(median, 'median', 'median')
|
1031 | 1016 |
|
1032 | 1017 | def max(self, axis='major', skipna=True):
|
1033 |
| - i = self._get_axis_number(axis) |
1034 |
| - |
1035 |
| - y = np.array(self.values) |
1036 |
| - if skipna: |
1037 |
| - np.putmask(y, np.isnan(y), -np.inf) |
1038 |
| - |
1039 |
| - result = y.max(axis=i) |
1040 |
| - result = np.where(np.isneginf(result), np.nan, result) |
1041 |
| - return self._wrap_result(result, axis) |
1042 |
| - |
| 1018 | + return self._reduce(nanops.nanmax, axis=axis, skipna=skipna) |
1043 | 1019 | _add_docs(max, 'maximum', 'maximum')
|
1044 | 1020 |
|
1045 | 1021 | def min(self, axis='major', skipna=True):
|
1046 |
| - i = self._get_axis_number(axis) |
1047 |
| - |
1048 |
| - y = np.array(self.values) |
1049 |
| - if skipna: |
1050 |
| - np.putmask(y, np.isnan(y), np.inf) |
1051 |
| - |
1052 |
| - result = y.min(axis=i) |
1053 |
| - result = np.where(np.isinf(result), np.nan, result) |
1054 |
| - return self._wrap_result(result, axis) |
1055 |
| - |
| 1022 | + return self._reduce(nanops.nanmin, axis=axis, skipna=skipna) |
1056 | 1023 | _add_docs(min, 'minimum', 'minimum')
|
1057 | 1024 |
|
1058 | 1025 | def shift(self, lags, axis='major'):
|
|
0 commit comments