25
25
_try_sort , _pfixed , _default_index ,
26
26
_infer_dtype )
27
27
from pandas .core .daterange import DateRange
28
- from pandas .core .generic import AxisProperty , PandasGeneric
28
+ from pandas .core .generic import AxisProperty , NDFrame
29
29
from pandas .core .index import Index , NULL_INDEX
30
30
from pandas .core .internals import BlockManager , make_block
31
31
from pandas .core .series import Series , _is_bool_indexer
@@ -94,7 +94,7 @@ def f(self, other):
94
94
#-------------------------------------------------------------------------------
95
95
# DataFrame class
96
96
97
- class DataFrame (PandasGeneric ):
97
+ class DataFrame (NDFrame ):
98
98
"""
99
99
Homogenously indexed table with named columns, with intelligent arithmetic
100
100
operations, slicing, reindexing, aggregation, etc. Can function
@@ -217,11 +217,19 @@ def astype(self, dtype):
217
217
-------
218
218
casted : DataFrame
219
219
"""
220
- return DataFrame (self ._data , dtype = dtype )
220
+ return type (self )(self ._data , dtype = dtype )
221
+
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 ]
221
229
222
230
@property
223
231
def _constructor (self ):
224
- return DataFrame
232
+ return type ( self )
225
233
226
234
#----------------------------------------------------------------------
227
235
# Class behavior
@@ -269,7 +277,7 @@ def copy(self):
269
277
"""
270
278
Make a copy of this DataFrame
271
279
"""
272
- return DataFrame (self ._data .copy ())
280
+ return type ( self ) (self ._data .copy ())
273
281
274
282
#----------------------------------------------------------------------
275
283
# Arithmetic methods
@@ -565,8 +573,8 @@ def transpose(self):
565
573
Returns a DataFrame with the rows/columns switched. Copy of data is not
566
574
made by default
567
575
"""
568
- return DataFrame (data = self .values .T , index = self .columns ,
569
- columns = self .index , copy = False )
576
+ return type ( self ) (data = self .values .T , index = self .columns ,
577
+ columns = self .index , copy = False )
570
578
T = property (transpose )
571
579
572
580
#----------------------------------------------------------------------
@@ -642,8 +650,8 @@ def __array__(self):
642
650
return self .values
643
651
644
652
def __array_wrap__ (self , result ):
645
- return DataFrame (result , index = self .index , columns = self .columns ,
646
- copy = False )
653
+ return type ( self ) (result , index = self .index , columns = self .columns ,
654
+ copy = False )
647
655
648
656
#----------------------------------------------------------------------
649
657
# getitem/setitem related
@@ -673,7 +681,7 @@ def __getitem__(self, item):
673
681
"""
674
682
if isinstance (item , slice ):
675
683
new_data = self ._data .get_slice (item , axis = 1 )
676
- return DataFrame (new_data )
684
+ return type ( self ) (new_data )
677
685
elif isinstance (item , np .ndarray ):
678
686
if len (item ) != len (self .index ):
679
687
raise ValueError ('Item wrong length %d instead of %d!' %
@@ -837,11 +845,11 @@ def _reindex_index(self, new_index, method):
837
845
if new_index is self .index :
838
846
return self .copy ()
839
847
new_data = self ._data .reindex_axis (new_index , method , axis = 1 )
840
- return DataFrame (new_data )
848
+ return type ( self ) (new_data )
841
849
842
850
def _reindex_columns (self , new_columns ):
843
851
new_data = self ._data .reindex_items (new_columns )
844
- return DataFrame (new_data )
852
+ return type ( self ) (new_data )
845
853
846
854
def reindex_like (self , other , method = None ):
847
855
"""
@@ -1039,14 +1047,14 @@ def fillna(self, value=None, method='pad'):
1039
1047
series = self ._series
1040
1048
for col , s in series .iteritems ():
1041
1049
result [col ] = s .fillna (method = method , value = value )
1042
- return DataFrame (result , index = self .index , columns = self .columns )
1050
+ return type ( self ) (result , index = self .index , columns = self .columns )
1043
1051
else :
1044
1052
# Float type values
1045
1053
if len (self .columns ) == 0 :
1046
1054
return self
1047
1055
1048
1056
new_data = self ._data .fillna (value )
1049
- return DataFrame (new_data , index = self .index , columns = self .columns )
1057
+ return type ( self ) (new_data , index = self .index , columns = self .columns )
1050
1058
1051
1059
#----------------------------------------------------------------------
1052
1060
# Rename
@@ -1122,7 +1130,7 @@ def _combine_frame(self, other, func, fill_value=None):
1122
1130
# some shortcuts
1123
1131
if fill_value is None :
1124
1132
if not self and not other :
1125
- return DataFrame (index = new_index )
1133
+ return type ( self ) (index = new_index )
1126
1134
elif not self :
1127
1135
return other * nan
1128
1136
elif not other :
@@ -1155,8 +1163,8 @@ def _combine_frame(self, other, func, fill_value=None):
1155
1163
other_vals [other_mask & mask ] = fill_value
1156
1164
1157
1165
result = func (this_vals , other_vals )
1158
- return DataFrame (result , index = new_index , columns = new_columns ,
1159
- copy = False )
1166
+ return type ( self ) (result , index = new_index , columns = new_columns ,
1167
+ copy = False )
1160
1168
1161
1169
def _indexed_same (self , other ):
1162
1170
same_index = self .index .equals (other .index )
@@ -1193,8 +1201,8 @@ def _combine_match_index(self, other, func, fill_value=None):
1193
1201
if fill_value is not None :
1194
1202
raise NotImplementedError
1195
1203
1196
- return DataFrame (func (values .T , other_vals ).T , index = new_index ,
1197
- columns = self .columns , copy = False )
1204
+ return type ( self ) (func (values .T , other_vals ).T , index = new_index ,
1205
+ columns = self .columns , copy = False )
1198
1206
1199
1207
def _combine_match_columns (self , other , func , fill_value = None ):
1200
1208
newCols = self .columns .union (other .index )
@@ -1206,15 +1214,15 @@ def _combine_match_columns(self, other, func, fill_value=None):
1206
1214
if fill_value is not None :
1207
1215
raise NotImplementedError
1208
1216
1209
- return DataFrame (func (this .values , other ), index = self .index ,
1210
- columns = newCols , copy = False )
1217
+ return type ( self ) (func (this .values , other ), index = self .index ,
1218
+ columns = newCols , copy = False )
1211
1219
1212
1220
def _combine_const (self , other , func ):
1213
1221
if not self :
1214
1222
return self
1215
1223
1216
- return DataFrame (func (self .values , other ), index = self .index ,
1217
- columns = self .columns , copy = False )
1224
+ return type ( self ) (func (self .values , other ), index = self .index ,
1225
+ columns = self .columns , copy = False )
1218
1226
1219
1227
def _compare_frame (self , other , func ):
1220
1228
if not self ._indexed_same (other ):
@@ -1479,7 +1487,7 @@ def _shift_block(blk, indexer):
1479
1487
new_data = self ._data .copy ()
1480
1488
new_data .axes [1 ] = self .index .shift (periods , offset )
1481
1489
1482
- return DataFrame (new_data )
1490
+ return type ( self ) (new_data )
1483
1491
1484
1492
def _shift_indexer (self , periods ):
1485
1493
# small reusable utility
@@ -1526,8 +1534,8 @@ def apply(self, func, axis=0, broadcast=False):
1526
1534
1527
1535
if isinstance (func , np .ufunc ):
1528
1536
results = func (self .values )
1529
- return DataFrame (data = results , index = self .index ,
1530
- columns = self .columns , copy = False )
1537
+ return type ( self ) (data = results , index = self .index ,
1538
+ columns = self .columns , copy = False )
1531
1539
else :
1532
1540
if not broadcast :
1533
1541
return self ._apply_standard (func , axis )
@@ -1683,7 +1691,7 @@ def _join_on(self, other, on):
1683
1691
raise Exception ('%s column not contained in this frame!' % on )
1684
1692
1685
1693
new_data = self ._data .join_on (other ._data , self [on ], axis = 1 )
1686
- return DataFrame (new_data )
1694
+ return type ( self ) (new_data )
1687
1695
1688
1696
def _join_index (self , other , how ):
1689
1697
join_index = self ._get_join_index (other , how )
@@ -1693,7 +1701,7 @@ def _join_index(self, other, how):
1693
1701
# merge blocks
1694
1702
merged_data = this_data .merge (other_data )
1695
1703
assert (merged_data .axes [1 ] is join_index ) # maybe unnecessary
1696
- return DataFrame (merged_data )
1704
+ return type ( self ) (merged_data )
1697
1705
1698
1706
def _get_join_index (self , other , how ):
1699
1707
if how == 'left' :
@@ -1788,7 +1796,7 @@ def corr(self):
1788
1796
correl [i , j ] = c
1789
1797
correl [j , i ] = c
1790
1798
1791
- return DataFrame (correl , index = cols , columns = cols )
1799
+ return type ( self ) (correl , index = cols , columns = cols )
1792
1800
1793
1801
def corrwith (self , other , axis = 0 , drop = False ):
1794
1802
"""
@@ -1858,7 +1866,7 @@ def describe(self):
1858
1866
tmp .quantile (.1 ), tmp .median (),
1859
1867
tmp .quantile (.9 ), tmp .max ()]
1860
1868
1861
- return DataFrame (data , index = cols_destat , columns = cols )
1869
+ return type ( self ) (data , index = cols_destat , columns = cols )
1862
1870
1863
1871
#----------------------------------------------------------------------
1864
1872
# ndarray-like stats methods
@@ -1939,31 +1947,6 @@ def sum(self, axis=0, numeric_only=False):
1939
1947
1940
1948
return Series (the_sum , index = axis_labels )
1941
1949
1942
- def cumsum (self , axis = 0 ):
1943
- """
1944
- Return DataFrame of cumulative sums over requested axis.
1945
-
1946
- Parameters
1947
- ----------
1948
- axis : {0, 1}
1949
- 0 for row-wise, 1 for column-wise
1950
-
1951
- Returns
1952
- -------
1953
- y : DataFrame
1954
- """
1955
- y = np .array (self .values , subok = True )
1956
- if not issubclass (y .dtype .type , np .int_ ):
1957
- mask = np .isnan (self .values )
1958
- y [mask ] = 0
1959
- result = y .cumsum (axis )
1960
- has_obs = (- mask ).astype (int ).cumsum (axis ) > 0
1961
- result [- has_obs ] = np .nan
1962
- else :
1963
- result = y .cumsum (axis )
1964
- return DataFrame (result , index = self .index , columns = self .columns ,
1965
- copy = False )
1966
-
1967
1950
def min (self , axis = 0 ):
1968
1951
"""
1969
1952
Return array or Series of minimums over requested axis.
@@ -1998,30 +1981,6 @@ def max(self, axis=0):
1998
1981
np .putmask (values , - np .isfinite (values ), - np .inf )
1999
1982
return Series (values .max (axis ), index = self ._get_agg_axis (axis ))
2000
1983
2001
- def cumprod (self , axis = 0 ):
2002
- """
2003
- Return cumulative product over requested axis as DataFrame
2004
-
2005
- Parameters
2006
- ----------
2007
- axis : {0, 1}
2008
- 0 for row-wise, 1 for column-wise
2009
-
2010
- Returns
2011
- -------
2012
- y : DataFrame
2013
- """
2014
- def get_cumprod (y ):
2015
- y = np .array (y )
2016
- mask = isnull (y )
2017
- if not issubclass (y .dtype .type , np .int_ ):
2018
- y [mask ] = 1
2019
- result = y .cumprod ()
2020
-
2021
- return result
2022
-
2023
- return self .apply (get_cumprod , axis = axis )
2024
-
2025
1984
def product (self , axis = 0 ):
2026
1985
"""
2027
1986
Return array or Series of products over requested axis.
0 commit comments