Skip to content

Commit 8021575

Browse files
committed
ENH: use _constructor properties to get factory function instead of type(self), for easier subclassing
1 parent 5ecc475 commit 8021575

File tree

3 files changed

+43
-33
lines changed

3 files changed

+43
-33
lines changed

pandas/core/frame.py

+31-29
Original file line numberDiff line numberDiff line change
@@ -217,19 +217,19 @@ def astype(self, dtype):
217217
-------
218218
casted : DataFrame
219219
"""
220-
return type(self)(self._data, dtype=dtype)
220+
return self._constructor(self._data, dtype=dtype)
221221

222222
def _wrap_array(self, arr, axes, copy=False):
223223
index, columns = axes
224-
return type(self)(arr, index=index, columns=columns, copy=copy)
224+
return self._constructor(arr, index=index, columns=columns, copy=copy)
225225

226226
@property
227227
def axes(self):
228228
return [self.index, self.columns]
229229

230230
@property
231231
def _constructor(self):
232-
return type(self)
232+
return DataFrame
233233

234234
#----------------------------------------------------------------------
235235
# Class behavior
@@ -277,7 +277,7 @@ def copy(self):
277277
"""
278278
Make a copy of this DataFrame
279279
"""
280-
return type(self)(self._data.copy())
280+
return self._constructor(self._data.copy())
281281

282282
#----------------------------------------------------------------------
283283
# Arithmetic methods
@@ -574,8 +574,8 @@ def transpose(self):
574574
Returns a DataFrame with the rows/columns switched. Copy of data is not
575575
made by default
576576
"""
577-
return type(self)(data=self.values.T, index=self.columns,
578-
columns=self.index, copy=False)
577+
return self._constructor(data=self.values.T, index=self.columns,
578+
columns=self.index, copy=False)
579579
T = property(transpose)
580580

581581
#----------------------------------------------------------------------
@@ -651,8 +651,8 @@ def __array__(self):
651651
return self.values
652652

653653
def __array_wrap__(self, result):
654-
return type(self)(result, index=self.index, columns=self.columns,
655-
copy=False)
654+
return self._constructor(result, index=self.index, columns=self.columns,
655+
copy=False)
656656

657657
#----------------------------------------------------------------------
658658
# getitem/setitem related
@@ -682,7 +682,7 @@ def __getitem__(self, item):
682682
"""
683683
if isinstance(item, slice):
684684
new_data = self._data.get_slice(item, axis=1)
685-
return type(self)(new_data)
685+
return self._constructor(new_data)
686686
elif isinstance(item, np.ndarray):
687687
if len(item) != len(self.index):
688688
raise ValueError('Item wrong length %d instead of %d!' %
@@ -846,11 +846,11 @@ def _reindex_index(self, new_index, method):
846846
if new_index is self.index:
847847
return self.copy()
848848
new_data = self._data.reindex_axis(new_index, method, axis=1)
849-
return type(self)(new_data)
849+
return self._constructor(new_data)
850850

851851
def _reindex_columns(self, new_columns):
852852
new_data = self._data.reindex_items(new_columns)
853-
return type(self)(new_data)
853+
return self._constructor(new_data)
854854

855855
def reindex_like(self, other, method=None):
856856
"""
@@ -1048,14 +1048,16 @@ def fillna(self, value=None, method='pad'):
10481048
series = self._series
10491049
for col, s in series.iteritems():
10501050
result[col] = s.fillna(method=method, value=value)
1051-
return type(self)(result, index=self.index, columns=self.columns)
1051+
return self._constructor(result, index=self.index,
1052+
columns=self.columns)
10521053
else:
10531054
# Float type values
10541055
if len(self.columns) == 0:
10551056
return self
10561057

10571058
new_data = self._data.fillna(value)
1058-
return type(self)(new_data, index=self.index, columns=self.columns)
1059+
return self._constructor(new_data, index=self.index,
1060+
columns=self.columns)
10591061

10601062
#----------------------------------------------------------------------
10611063
# Rename
@@ -1131,7 +1133,7 @@ def _combine_frame(self, other, func, fill_value=None):
11311133
# some shortcuts
11321134
if fill_value is None:
11331135
if not self and not other:
1134-
return type(self)(index=new_index)
1136+
return self._constructor(index=new_index)
11351137
elif not self:
11361138
return other * nan
11371139
elif not other:
@@ -1164,8 +1166,8 @@ def _combine_frame(self, other, func, fill_value=None):
11641166
other_vals[other_mask & mask] = fill_value
11651167

11661168
result = func(this_vals, other_vals)
1167-
return type(self)(result, index=new_index, columns=new_columns,
1168-
copy=False)
1169+
return self._constructor(result, index=new_index, columns=new_columns,
1170+
copy=False)
11691171

11701172
def _indexed_same(self, other):
11711173
same_index = self.index.equals(other.index)
@@ -1202,8 +1204,8 @@ def _combine_match_index(self, other, func, fill_value=None):
12021204
if fill_value is not None:
12031205
raise NotImplementedError
12041206

1205-
return type(self)(func(values.T, other_vals).T, index=new_index,
1206-
columns=self.columns, copy=False)
1207+
return self._constructor(func(values.T, other_vals).T, index=new_index,
1208+
columns=self.columns, copy=False)
12071209

12081210
def _combine_match_columns(self, other, func, fill_value=None):
12091211
newCols = self.columns.union(other.index)
@@ -1215,15 +1217,15 @@ def _combine_match_columns(self, other, func, fill_value=None):
12151217
if fill_value is not None:
12161218
raise NotImplementedError
12171219

1218-
return type(self)(func(this.values, other), index=self.index,
1219-
columns=newCols, copy=False)
1220+
return self._constructor(func(this.values, other), index=self.index,
1221+
columns=newCols, copy=False)
12201222

12211223
def _combine_const(self, other, func):
12221224
if not self:
12231225
return self
12241226

1225-
return type(self)(func(self.values, other), index=self.index,
1226-
columns=self.columns, copy=False)
1227+
return self._constructor(func(self.values, other), index=self.index,
1228+
columns=self.columns, copy=False)
12271229

12281230
def _compare_frame(self, other, func):
12291231
if not self._indexed_same(other):
@@ -1488,7 +1490,7 @@ def _shift_block(blk, indexer):
14881490
new_data = self._data.copy()
14891491
new_data.axes[1] = self.index.shift(periods, offset)
14901492

1491-
return type(self)(new_data)
1493+
return self._constructor(new_data)
14921494

14931495
def _shift_indexer(self, periods):
14941496
# small reusable utility
@@ -1535,8 +1537,8 @@ def apply(self, func, axis=0, broadcast=False):
15351537

15361538
if isinstance(func, np.ufunc):
15371539
results = func(self.values)
1538-
return type(self)(data=results, index=self.index,
1539-
columns=self.columns, copy=False)
1540+
return self._constructor(data=results, index=self.index,
1541+
columns=self.columns, copy=False)
15401542
else:
15411543
if not broadcast:
15421544
return self._apply_standard(func, axis)
@@ -1692,7 +1694,7 @@ def _join_on(self, other, on):
16921694
raise Exception('%s column not contained in this frame!' % on)
16931695

16941696
new_data = self._data.join_on(other._data, self[on], axis=1)
1695-
return type(self)(new_data)
1697+
return self._constructor(new_data)
16961698

16971699
def _join_index(self, other, how):
16981700
join_index = self._get_join_index(other, how)
@@ -1702,7 +1704,7 @@ def _join_index(self, other, how):
17021704
# merge blocks
17031705
merged_data = this_data.merge(other_data)
17041706
assert(merged_data.axes[1] is join_index) # maybe unnecessary
1705-
return type(self)(merged_data)
1707+
return self._constructor(merged_data)
17061708

17071709
def _get_join_index(self, other, how):
17081710
if how == 'left':
@@ -1797,7 +1799,7 @@ def corr(self):
17971799
correl[i, j] = c
17981800
correl[j, i] = c
17991801

1800-
return type(self)(correl, index=cols, columns=cols)
1802+
return self._constructor(correl, index=cols, columns=cols)
18011803

18021804
def corrwith(self, other, axis=0, drop=False):
18031805
"""
@@ -1867,7 +1869,7 @@ def describe(self):
18671869
tmp.quantile(.1), tmp.median(),
18681870
tmp.quantile(.9), tmp.max()]
18691871

1870-
return type(self)(data, index=cols_destat, columns=cols)
1872+
return self._constructor(data, index=cols_destat, columns=cols)
18711873

18721874
#----------------------------------------------------------------------
18731875
# ndarray-like stats methods

pandas/core/generic.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ class NDFrame(Picklable):
5454
def __init__(self, data, axes=None, copy=False):
5555
self._data = data
5656

57+
@property
58+
def _constructor(self):
59+
return NDFrame
60+
5761
@property
5862
def axes(self):
5963
return self._data.axes
@@ -89,7 +93,7 @@ def consolidate(self):
8993
cons_data = self._data.consolidate()
9094
if cons_data is self._data:
9195
cons_data = cons_data.copy()
92-
return type(self)(cons_data)
96+
return self._constructor(cons_data)
9397

9498
@property
9599
def _is_mixed_type(self):
@@ -174,7 +178,7 @@ def _reindex_axis(self, new_index, fill_method, axis):
174178
else:
175179
new_data = self._data.reindex_axis(new_index, axis=axis,
176180
method=fill_method)
177-
return type(self)(new_data)
181+
return self._constructor(new_data)
178182

179183
def truncate(self, before=None, after=None):
180184
"""Function truncate a sorted DataFrame / Series before and/or after

pandas/core/panel.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -246,10 +246,14 @@ def _get_plane_axes(self, axis):
246246

247247
return index, columns
248248

249+
@property
250+
def _constructor(self):
251+
return WidePanel
252+
249253
def _wrap_array(self, arr, axes, copy=False):
250254
items, major, minor = axes
251-
return type(self)(arr, items=items, major_axis=major,
252-
minor_axis=minor, copy=copy)
255+
return self._constructor(arr, items=items, major_axis=major,
256+
minor_axis=minor, copy=copy)
253257

254258
def copy(self):
255259
"""

0 commit comments

Comments
 (0)