Skip to content

Commit ab74e77

Browse files
committed
ENH: made things more generic, reduced code dup
1 parent 05123af commit ab74e77

File tree

4 files changed

+112
-86
lines changed

4 files changed

+112
-86
lines changed

pandas/core/frame.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
_try_sort, _pfixed, _default_index,
2626
_infer_dtype)
2727
from pandas.core.daterange import DateRange
28-
from pandas.core.generic import AxisProperty, PandasGeneric
28+
from pandas.core.generic import AxisProperty, NDFrame
2929
from pandas.core.index import Index, NULL_INDEX
3030
from pandas.core.internals import BlockManager, make_block
3131
from pandas.core.series import Series, _is_bool_indexer
@@ -94,7 +94,7 @@ def f(self, other):
9494
#-------------------------------------------------------------------------------
9595
# DataFrame class
9696

97-
class DataFrame(PandasGeneric):
97+
class DataFrame(NDFrame):
9898
"""
9999
Homogenously indexed table with named columns, with intelligent arithmetic
100100
operations, slicing, reindexing, aggregation, etc. Can function
@@ -219,6 +219,14 @@ def astype(self, dtype):
219219
"""
220220
return type(self)(self._data, dtype=dtype)
221221

222+
def _wrap_array(self, arr, axes, copy=False):
223+
index, columns = axes
224+
return type(self)(arr, index=index, columns=columns, copy=copy)
225+
226+
@property
227+
def axes(self):
228+
return [self.index, self.columns]
229+
222230
@property
223231
def _constructor(self):
224232
return type(self)

pandas/core/generic.py

Lines changed: 70 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,18 @@ def __set__(self, obj, value):
3737
data = getattr(obj, '_data')
3838
data.set_axis(self.axis, value)
3939

40-
class NDFrame(object):
41-
"""
42-
N-dimensional labeled array data structure with potentially heterogenous
43-
dtypes along one axis
44-
"""
40+
class NDFrame(Picklable):
41+
42+
_AXIS_NUMBERS = {
43+
'index' : 0,
44+
'columns' : 1
45+
}
46+
47+
_AXIS_ALIASES = {}
48+
_AXIS_NAMES = dict((v, k) for k, v in _AXIS_NUMBERS.iteritems())
49+
50+
_default_stat_axis = 0
51+
4552
def __init__(self, data, axes=None, copy=False):
4653
self._data = data
4754
self.axes = axes
@@ -50,21 +57,14 @@ def __repr__(self):
5057
# TODO
5158
return 'NDFrame'
5259

60+
@property
61+
def values(self):
62+
return self._data.as_matrix()
63+
5364
@property
5465
def ndim(self):
5566
return self._data.ndim
5667

57-
class PandasGeneric(Picklable):
58-
59-
_AXIS_NUMBERS = {
60-
'index' : 0,
61-
'columns' : 1
62-
}
63-
64-
_AXIS_ALIASES = {}
65-
66-
_AXIS_NAMES = dict((v, k) for k, v in _AXIS_NUMBERS.iteritems())
67-
6868
#----------------------------------------------------------------------
6969
# Consolidation of internals
7070

@@ -121,6 +121,10 @@ def _get_axis(self, axis):
121121
name = self._get_axis_name(axis)
122122
return getattr(self, name)
123123

124+
@property
125+
def axes(self):
126+
return self._data.axes
127+
124128
def groupby(self, mapper):
125129
"""
126130
Goup series using mapper (dict or key function, apply given
@@ -167,7 +171,7 @@ def _reindex_axis(self, new_index, fill_method, axis):
167171
method=fill_method)
168172
return type(self)(new_data)
169173

170-
def cumsum(self, axis=0):
174+
def cumsum(self, axis=None):
171175
"""
172176
Return DataFrame of cumulative sums over requested axis.
173177
@@ -180,6 +184,11 @@ def cumsum(self, axis=0):
180184
-------
181185
y : DataFrame
182186
"""
187+
if axis is None:
188+
axis = self._default_stat_axis
189+
else:
190+
axis = self._get_axis_number(axis)
191+
183192
y = self.values.copy()
184193
if not issubclass(y.dtype.type, np.int_):
185194
mask = np.isnan(self.values)
@@ -188,10 +197,12 @@ def cumsum(self, axis=0):
188197
np.putmask(result, mask, np.nan)
189198
else:
190199
result = y.cumsum(axis)
191-
return type(self)(result, index=self.index, columns=self.columns,
192-
copy=False)
200+
return self._wrap_array(result, self.axes, copy=False)
201+
202+
def _wrap_array(self, array, axes, copy=False):
203+
raise NotImplementedError
193204

194-
def cumprod(self, axis=0):
205+
def cumprod(self, axis=None):
195206
"""
196207
Return cumulative product over requested axis as DataFrame
197208
@@ -204,6 +215,11 @@ def cumprod(self, axis=0):
204215
-------
205216
y : DataFrame
206217
"""
218+
if axis is None:
219+
axis = self._default_stat_axis
220+
else:
221+
axis = self._get_axis_number(axis)
222+
207223
y = self.values.copy()
208224
if not issubclass(y.dtype.type, np.int_):
209225
mask = np.isnan(self.values)
@@ -212,6 +228,38 @@ def cumprod(self, axis=0):
212228
np.putmask(result, mask, np.nan)
213229
else:
214230
result = y.cumprod(axis)
215-
return type(self)(result, index=self.index, columns=self.columns,
216-
copy=False)
231+
return self._wrap_array(result, self.axes, copy=False)
232+
233+
def _values_aggregate(self, func, axis, fill_value):
234+
axis = self._get_axis_number(axis)
235+
236+
values = self.values
237+
mask = np.isfinite(values)
238+
239+
if fill_value is not None:
240+
values = values.copy()
241+
values[-mask] = fill_value
242+
243+
result = func(values, axis=axis)
244+
count = mask.sum(axis=axis)
245+
246+
result[count == 0] = np.NaN
247+
248+
return result
249+
250+
def _values_accum(self, func, axis, fill_value):
251+
axis = self._get_axis_number(axis)
252+
253+
values = self.values
254+
mask = np.isfinite(values)
255+
256+
if fill_value is not None:
257+
values = values.copy()
258+
values[-mask] = fill_value
259+
260+
result = func(values, axis=axis)
261+
262+
if fill_value is not None:
263+
result[-mask] = np.NaN
217264

265+
return result

pandas/core/panel.py

Lines changed: 27 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from pandas.core.index import Index
1515
from pandas.core.internals import BlockManager, make_block
1616
from pandas.core.frame import DataFrame
17-
from pandas.core.generic import AxisProperty, PandasGeneric, Picklable
17+
from pandas.core.generic import AxisProperty, NDFrame, Picklable
1818
import pandas.core.common as common
1919
import pandas._tseries as _tseries
2020

@@ -153,7 +153,7 @@ def dims(self): # pragma: no cover
153153
FutureWarning)
154154
return self.shape
155155

156-
class WidePanel(Panel, PandasGeneric):
156+
class WidePanel(Panel, NDFrame):
157157
"""
158158
Represents wide format panel data, stored as 3-dimensional array
159159
@@ -181,6 +181,9 @@ class WidePanel(Panel, PandasGeneric):
181181
2 : 'minor_axis'
182182
}
183183

184+
# major
185+
_default_stat_axis = 1
186+
184187
items = AxisProperty(0)
185188
major_axis = AxisProperty(1)
186189
minor_axis = AxisProperty(2)
@@ -243,6 +246,11 @@ def _get_plane_axes(self, axis):
243246

244247
return index, columns
245248

249+
def _wrap_array(self, arr, axes, copy=False):
250+
items, major, minor = axes
251+
return type(self)(arr, items=items, major_axis=major,
252+
minor_axis=minor, copy=copy)
253+
246254
def copy(self):
247255
"""
248256
Return a copy of WidePanel (only values ndarray copied)
@@ -581,20 +589,6 @@ def minor_xs(self, key, copy=True):
581589
new_data = self._data.xs(key, axis=2, copy=copy)
582590
return DataFrame(new_data)
583591

584-
def getMinorXS(self, key): # pragma: no cover
585-
warnings.warn("getMinorXS has been replaced by the minor_xs function "
586-
"please modify your code accordingly",
587-
FutureWarning)
588-
589-
return self.minor_xs(key)
590-
591-
def getMajorXS(self, key): # pragma: no cover
592-
warnings.warn("getMajorXS has been replaced by the major_xs function "
593-
"please modify your code accordingly",
594-
FutureWarning)
595-
596-
return self.major_xs(key)
597-
598592
def groupby(self, function, axis='major'):
599593
"""
600594
Group data on given axis, returning GroupBy object
@@ -721,40 +715,6 @@ def apply(self, func, axis='major'):
721715
result = np.apply_along_axis(func, i, self.values)
722716
return self._wrap_result(result, axis=axis)
723717

724-
def _values_aggregate(self, func, axis, fill_value):
725-
axis = self._get_axis_number(axis)
726-
727-
values = self.values
728-
mask = np.isfinite(values)
729-
730-
if fill_value is not None:
731-
values = values.copy()
732-
values[-mask] = fill_value
733-
734-
result = func(values, axis=axis)
735-
count = mask.sum(axis=axis)
736-
737-
result[count == 0] = np.NaN
738-
739-
return result
740-
741-
def _values_accum(self, func, axis, fill_value):
742-
axis = self._get_axis_number(axis)
743-
744-
values = self.values
745-
mask = np.isfinite(values)
746-
747-
if fill_value is not None:
748-
values = values.copy()
749-
values[-mask] = fill_value
750-
751-
result = func(values, axis=axis)
752-
753-
if fill_value is not None:
754-
result[-mask] = np.NaN
755-
756-
return result
757-
758718
def _array_method(self, func, axis='major', fill_value=None):
759719
"""
760720
Parameters
@@ -811,16 +771,6 @@ def sum(self, axis='major'):
811771
"""
812772
return self._array_method(np.sum, axis=axis, fill_value=0)
813773

814-
def cumsum(self, axis='major'):
815-
"""
816-
817-
Returns
818-
-------
819-
y : WidePanel
820-
"""
821-
result = self._values_accum(np.cumsum, axis=axis, fill_value=0)
822-
return self._wrap_result(result, axis)
823-
824774
def mean(self, axis='major'):
825775
"""
826776
@@ -1001,6 +951,23 @@ def select(self, crit, axis=0):
1001951
"""
1002952
return self._select_generic(crit, axis=axis)
1003953

954+
#----------------------------------------------------------------------
955+
# Deprecated stuff
956+
957+
def getMinorXS(self, key): # pragma: no cover
958+
warnings.warn("getMinorXS has been replaced by the minor_xs function "
959+
"please modify your code accordingly",
960+
FutureWarning)
961+
962+
return self.minor_xs(key)
963+
964+
def getMajorXS(self, key): # pragma: no cover
965+
warnings.warn("getMajorXS has been replaced by the major_xs function "
966+
"please modify your code accordingly",
967+
FutureWarning)
968+
969+
return self.major_xs(key)
970+
1004971
#-------------------------------------------------------------------------------
1005972
# LongPanel and friends
1006973

pandas/core/series.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
from pandas.core.common import isnull, notnull, _ensure_index
1717
from pandas.core.daterange import DateRange
18-
from pandas.core.generic import PandasGeneric
18+
from pandas.core.generic import NDFrame
1919
from pandas.core.index import Index
2020
import pandas.core.datetools as datetools
2121
import pandas._tseries as _tseries
@@ -92,7 +92,7 @@ def f(self, other, fill_value=None):
9292
#-------------------------------------------------------------------------------
9393
# Series class
9494

95-
class Series(np.ndarray, PandasGeneric):
95+
class Series(np.ndarray, NDFrame):
9696
"""
9797
Generic indexed (labeled) vector (time series or cross-section)
9898
@@ -194,6 +194,9 @@ def __new__(cls, data, index=None, dtype=None, copy=False):
194194

195195
return subarr
196196

197+
def __init__(self, *args, **kwargs):
198+
pass
199+
197200
def __hash__(self):
198201
raise TypeError('unhashable type')
199202

0 commit comments

Comments
 (0)