@@ -47,8 +47,7 @@ def _single_replace(self, to_replace, method, inplace, limit):
4747 if values .dtype == orig_dtype and inplace :
4848 return
4949
50- result = pd .Series (values , index = self .index , name = self .name ,
51- dtype = self .dtype )
50+ result = pd .Series (values , index = self .index , dtype = self .dtype ).__finalize__ (self )
5251
5352 if inplace :
5453 self ._data = result ._data
@@ -72,7 +71,7 @@ class NDFrame(PandasObject):
7271 _internal_names = [
7372 '_data' , 'name' , '_cacher' , '_subtyp' , '_index' , '_default_kind' , '_default_fill_value' ]
7473 _internal_names_set = set (_internal_names )
75- _prop_attributes = []
74+ _metadata = []
7675
7776 def __init__ (self , data , axes = None , copy = False , dtype = None , fastpath = False ):
7877
@@ -413,7 +412,7 @@ def transpose(self, *args, **kwargs):
413412 new_values = self .values .transpose (axes_numbers )
414413 if kwargs .get ('copy' ) or (len (args ) and args [- 1 ]):
415414 new_values = new_values .copy ()
416- return self ._constructor (new_values , ** new_axes )
415+ return self ._constructor (new_values , ** new_axes ). __finalize__ ( self )
417416
418417 def swapaxes (self , axis1 , axis2 , copy = True ):
419418 """
@@ -439,7 +438,7 @@ def swapaxes(self, axis1, axis2, copy=True):
439438 if copy :
440439 new_values = new_values .copy ()
441440
442- return self ._constructor (new_values , * new_axes )
441+ return self ._constructor (new_values , * new_axes ). __finalize__ ( self )
443442
444443 def pop (self , item ):
445444 """
@@ -543,7 +542,7 @@ def f(x):
543542 self ._clear_item_cache ()
544543
545544 else :
546- return result ._propogate_attributes (self )
545+ return result .__finalize__ (self )
547546
548547 rename .__doc__ = _shared_docs ['rename' ]
549548
@@ -655,14 +654,14 @@ def __abs__(self):
655654
656655 def _wrap_array (self , arr , axes , copy = False ):
657656 d = self ._construct_axes_dict_from (self , axes , copy = copy )
658- return self ._constructor (arr , ** d )
657+ return self ._constructor (arr , ** d ). __finalize__ ( self )
659658
660659 def __array__ (self , dtype = None ):
661660 return _values_from_object (self )
662661
663662 def __array_wrap__ (self , result ):
664663 d = self ._construct_axes_dict (self ._AXIS_ORDERS , copy = False )
665- return self ._constructor (result , ** d )
664+ return self ._constructor (result , ** d ). __finalize__ ( self )
666665
667666 def to_dense (self ):
668667 # compat
@@ -1024,7 +1023,7 @@ def take(self, indices, axis=0, convert=True):
10241023 new_data = self ._data .reindex_axis (new_items , indexer = indices , axis = 0 )
10251024 else :
10261025 new_data = self ._data .take (indices , axis = baxis )
1027- return self ._constructor (new_data )
1026+ return self ._constructor (new_data ). __finalize__ ( self )
10281027
10291028 # TODO: Check if this was clearer in 0.12
10301029 def select (self , crit , axis = 0 ):
@@ -1135,7 +1134,7 @@ def add_prefix(self, prefix):
11351134 with_prefix : type of caller
11361135 """
11371136 new_data = self ._data .add_prefix (prefix )
1138- return self ._constructor (new_data )
1137+ return self ._constructor (new_data ). __finalize__ ( self )
11391138
11401139 def add_suffix (self , suffix ):
11411140 """
@@ -1150,7 +1149,7 @@ def add_suffix(self, suffix):
11501149 with_suffix : type of caller
11511150 """
11521151 new_data = self ._data .add_suffix (suffix )
1153- return self ._constructor (new_data )
1152+ return self ._constructor (new_data ). __finalize__ ( self )
11541153
11551154 def sort_index (self , axis = 0 , ascending = True ):
11561155 """
@@ -1244,7 +1243,8 @@ def reindex(self, *args, **kwargs):
12441243 return self
12451244
12461245 # perform the reindex on the axes
1247- return self ._reindex_axes (axes , level , limit , method , fill_value , copy , takeable = takeable )._propogate_attributes (self )
1246+ return self ._reindex_axes (axes , level , limit ,
1247+ method , fill_value , copy , takeable = takeable ).__finalize__ (self )
12481248
12491249 def _reindex_axes (self , axes , level , limit , method , fill_value , copy , takeable = False ):
12501250 """ perform the reinxed for all the axes """
@@ -1332,7 +1332,7 @@ def reindex_axis(self, labels, axis=0, method=None, level=None, copy=True,
13321332 new_index , indexer = axis_values .reindex (labels , method , level ,
13331333 limit = limit , copy_if_needed = True )
13341334 return self ._reindex_with_indexers ({axis : [new_index , indexer ]}, method = method , fill_value = fill_value ,
1335- limit = limit , copy = copy )._propogate_attributes (self )
1335+ limit = limit , copy = copy ).__finalize__ (self )
13361336
13371337 def _reindex_with_indexers (self , reindexers , method = None , fill_value = np .nan , limit = None , copy = False , allow_dups = False ):
13381338 """ allow_dups indicates an internal call here """
@@ -1370,7 +1370,7 @@ def _reindex_with_indexers(self, reindexers, method=None, fill_value=np.nan, lim
13701370 if copy and new_data is self ._data :
13711371 new_data = new_data .copy ()
13721372
1373- return self ._constructor (new_data )
1373+ return self ._constructor (new_data ). __finalize__ ( self )
13741374
13751375 def _reindex_axis (self , new_index , fill_method , axis , copy ):
13761376 new_data = self ._data .reindex_axis (new_index , axis = axis ,
@@ -1379,7 +1379,7 @@ def _reindex_axis(self, new_index, fill_method, axis, copy):
13791379 if new_data is self ._data and not copy :
13801380 return self
13811381 else :
1382- return self ._constructor (new_data )
1382+ return self ._constructor (new_data ). __finalize__ ( self )
13831383
13841384 def filter (self , items = None , like = None , regex = None , axis = None ):
13851385 """
@@ -1421,9 +1421,18 @@ def filter(self, items=None, like=None, regex=None, axis=None):
14211421 #----------------------------------------------------------------------
14221422 # Attribute access
14231423
1424- def _propogate_attributes (self , other ):
1425- """ propogate attributes from other to self"""
1426- for name in self ._prop_attributes :
1424+ def __finalize__ (self , other , method = None , ** kwargs ):
1425+ """
1426+ propagate metadata from other to self
1427+
1428+ Parameters
1429+ ----------
1430+ other : the object from which to get the attributes that we are going to propagate
1431+ method : optional, a passed method name ; possibily to take different types
1432+ of propagation actions based on this
1433+
1434+ """
1435+ for name in self ._metadata :
14271436 object .__setattr__ (self , name , getattr (other , name , None ))
14281437 return self
14291438
@@ -1484,7 +1493,7 @@ def consolidate(self, inplace=False):
14841493 cons_data = self ._protect_consolidate (f )
14851494 if cons_data is self ._data :
14861495 cons_data = cons_data .copy ()
1487- return self ._constructor (cons_data )
1496+ return self ._constructor (cons_data ). __finalize__ ( self )
14881497
14891498 @property
14901499 def _is_mixed_type (self ):
@@ -1504,10 +1513,10 @@ def _protect_consolidate(self, f):
15041513 return result
15051514
15061515 def _get_numeric_data (self ):
1507- return self ._constructor (self ._data .get_numeric_data ())
1516+ return self ._constructor (self ._data .get_numeric_data ()). __finalize__ ( self )
15081517
15091518 def _get_bool_data (self ):
1510- return self ._constructor (self ._data .get_bool_data ())
1519+ return self ._constructor (self ._data .get_bool_data ()). __finalize__ ( self )
15111520
15121521 #----------------------------------------------------------------------
15131522 # Internal Interface Methods
@@ -1584,7 +1593,7 @@ def as_blocks(self, columns=None):
15841593 for b in self ._data .blocks :
15851594 b = b .reindex_items_from (columns or b .items )
15861595 bd [str (b .dtype )] = self ._constructor (
1587- BlockManager ([b ], [b .items , self .index ]))
1596+ BlockManager ([b ], [b .items , self .index ])). __finalize__ ( self )
15881597 return bd
15891598
15901599 @property
@@ -1608,7 +1617,7 @@ def astype(self, dtype, copy=True, raise_on_error=True):
16081617
16091618 mgr = self ._data .astype (
16101619 dtype , copy = copy , raise_on_error = raise_on_error )
1611- return self ._constructor (mgr )._propogate_attributes (self )
1620+ return self ._constructor (mgr ).__finalize__ (self )
16121621
16131622 def copy (self , deep = True ):
16141623 """
@@ -1626,7 +1635,7 @@ def copy(self, deep=True):
16261635 data = self ._data
16271636 if deep :
16281637 data = data .copy ()
1629- return self ._constructor (data )._propogate_attributes (self )
1638+ return self ._constructor (data ).__finalize__ (self )
16301639
16311640 def convert_objects (self , convert_dates = True , convert_numeric = False , copy = True ):
16321641 """
@@ -1642,7 +1651,9 @@ def convert_objects(self, convert_dates=True, convert_numeric=False, copy=True):
16421651 -------
16431652 converted : asm as input object
16441653 """
1645- return self ._constructor (self ._data .convert (convert_dates = convert_dates , convert_numeric = convert_numeric , copy = copy ))
1654+ return self ._constructor (self ._data .convert (convert_dates = convert_dates ,
1655+ convert_numeric = convert_numeric ,
1656+ copy = copy )).__finalize__ (self )
16461657
16471658 #----------------------------------------------------------------------
16481659 # Filling NA's
@@ -1713,7 +1724,7 @@ def fillna(self, value=None, method=None, axis=0, inplace=False,
17131724
17141725 # fill in 2d chunks
17151726 result = dict ([ (col ,s .fillna (method = method , value = value )) for col , s in compat .iteritems (self ) ])
1716- return self ._constructor .from_dict (result )
1727+ return self ._constructor .from_dict (result ). __finalize__ ( self )
17171728
17181729 # 2d or less
17191730 method = com ._clean_fill_method (method )
@@ -1750,7 +1761,7 @@ def fillna(self, value=None, method=None, axis=0, inplace=False,
17501761 if inplace :
17511762 self ._data = new_data
17521763 else :
1753- return self ._constructor (new_data )
1764+ return self ._constructor (new_data ). __finalize__ ( self )
17541765
17551766 def ffill (self , axis = 0 , inplace = False , limit = None , downcast = None ):
17561767 return self .fillna (method = 'ffill' , axis = axis , inplace = inplace ,
@@ -1991,7 +2002,7 @@ def replace(self, to_replace=None, value=None, inplace=False, limit=None,
19912002 if inplace :
19922003 self ._data = new_data
19932004 else :
1994- return self ._constructor (new_data )
2005+ return self ._constructor (new_data ). __finalize__ ( self )
19952006
19962007 def interpolate (self , method = 'linear' , axis = 0 , limit = None , inplace = False ,
19972008 downcast = 'infer' , ** kwargs ):
@@ -2101,7 +2112,7 @@ def interpolate(self, method='linear', axis=0, limit=None, inplace=False,
21012112 else :
21022113 self ._data = new_data
21032114 else :
2104- res = self ._constructor (new_data , index = self . index )
2115+ res = self ._constructor (new_data ). __finalize__ ( self )
21052116 if axis == 1 :
21062117 res = res .T
21072118 return res
@@ -2113,13 +2124,13 @@ def isnull(self):
21132124 """
21142125 Return a boolean same-sized object indicating if the values are null
21152126 """
2116- return self .__class__ (isnull (self ),** self ._construct_axes_dict ())._propogate_attributes (self )
2127+ return self .__class__ (isnull (self ),** self ._construct_axes_dict ()).__finalize__ (self )
21172128
21182129 def notnull (self ):
21192130 """
21202131 Return a boolean same-sized object indicating if the values are not null
21212132 """
2122- return self .__class__ (notnull (self ),** self ._construct_axes_dict ())._propogate_attributes (self )
2133+ return self .__class__ (notnull (self ),** self ._construct_axes_dict ()).__finalize__ (self )
21232134
21242135 def clip (self , lower = None , upper = None , out = None ):
21252136 """
@@ -2484,7 +2495,7 @@ def _align_frame(self, other, join='outer', axis=None, level=None,
24842495 left = left .fillna (axis = fill_axis , method = method , limit = limit )
24852496 right = right .fillna (axis = fill_axis , method = method , limit = limit )
24862497
2487- return left , right
2498+ return left . __finalize__ ( self ) , right . __finalize__ ( other )
24882499
24892500 def _align_series (self , other , join = 'outer' , axis = None , level = None ,
24902501 copy = True , fill_value = None , method = None , limit = None ,
@@ -2543,7 +2554,7 @@ def _align_series(self, other, join='outer', axis=None, level=None,
25432554 right_result .fillna (fill_value , method = method ,
25442555 limit = limit ))
25452556 else :
2546- return left_result , right_result
2557+ return left_result . __finalize__ ( self ) , right_result . __finalize__ ( other )
25472558
25482559 def where (self , cond , other = np .nan , inplace = False , axis = None , level = None ,
25492560 try_cast = False , raise_on_error = True ):
@@ -2680,7 +2691,7 @@ def where(self, cond, other=np.nan, inplace=False, axis=None, level=None,
26802691 new_data = self ._data .where (
26812692 other , cond , align = axis is None , raise_on_error = raise_on_error , try_cast = try_cast )
26822693
2683- return self ._constructor (new_data )
2694+ return self ._constructor (new_data ). __finalize__ ( self )
26842695
26852696 def mask (self , cond ):
26862697 """
@@ -2728,7 +2739,7 @@ def shift(self, periods=1, freq=None, axis=0, **kwds):
27282739 else :
27292740 return self .tshift (periods , freq , ** kwds )
27302741
2731- return self ._constructor (new_data )
2742+ return self ._constructor (new_data ). __finalize__ ( self )
27322743
27332744 def tshift (self , periods = 1 , freq = None , axis = 0 , ** kwds ):
27342745 """
@@ -2789,7 +2800,7 @@ def tshift(self, periods=1, freq=None, axis=0, **kwds):
27892800 new_data = self ._data .copy ()
27902801 new_data .axes [block_axis ] = index .shift (periods , offset )
27912802
2792- return self ._constructor (new_data )
2803+ return self ._constructor (new_data ). __finalize__ ( self )
27932804
27942805 def truncate (self , before = None , after = None , copy = True ):
27952806 """Truncates a sorted NDFrame before and/or after some particular
@@ -2864,7 +2875,7 @@ def tz_convert(self, tz, axis=0, copy=True):
28642875 new_obj ._set_axis (0 , new_ax )
28652876 self ._clear_item_cache ()
28662877
2867- return new_obj
2878+ return new_obj . __finalize__ ( self )
28682879
28692880 def tz_localize (self , tz , axis = 0 , copy = True , infer_dst = False ):
28702881 """
@@ -2902,7 +2913,7 @@ def tz_localize(self, tz, axis=0, copy=True, infer_dst=False):
29022913 new_obj ._set_axis (0 , new_ax )
29032914 self ._clear_item_cache ()
29042915
2905- return new_obj
2916+ return new_obj . __finalize__ ( self )
29062917
29072918 #----------------------------------------------------------------------
29082919 # Numeric Methods
@@ -3128,7 +3139,7 @@ def func(self, axis=None, dtype=None, out=None, skipna=True, **kwargs):
31283139
31293140 d = self ._construct_axes_dict ()
31303141 d ['copy' ] = False
3131- return self ._constructor (result , ** d )._propogate_attributes (self )
3142+ return self ._constructor (result , ** d ).__finalize__ (self )
31323143
31333144 func .__name__ = name
31343145 return func
0 commit comments