1313
1414class TestnanopsDataFrame (tm .TestCase ):
1515 def setUp (self ):
16+ np .random .seed (11235 )
17+
1618 self .arr_shape = (11 , 7 , 5 )
1719
1820 self .arr_float = np .random .randn (* self .arr_shape )
@@ -118,11 +120,38 @@ def check_results(self, targ, res, axis):
118120 res = getattr (res , 'values' , res )
119121 if axis != 0 and hasattr (targ , 'shape' ) and targ .ndim :
120122 res = np .split (res , [targ .shape [0 ]], axis = 0 )[0 ]
121- tm .assert_almost_equal (targ , res )
123+ try :
124+ tm .assert_almost_equal (targ , res )
125+ except :
126+ # There are sometimes rounding errors with
127+ # complex and object dtypes.
128+ # If it isn't one of those, re-raise the error.
129+ if not hasattr (res , 'dtype' ) or res .dtype .kind not in ['c' , 'O' ]:
130+ raise
131+ # convert object dtypes to something that can be split into
132+ # real and imaginary parts
133+ if res .dtype .kind == 'O' :
134+ if targ .dtype .kind != 'O' :
135+ res = res .astype (targ .dtype )
136+ else :
137+ try :
138+ res = res .astype ('c16' )
139+ except :
140+ res = res .astype ('f8' )
141+ try :
142+ targ = targ .astype ('c16' )
143+ except :
144+ targ = targ .astype ('f8' )
145+ # there should never be a case where numpy returns an object
146+ # but nanops doesn't, so make that an exception
147+ elif targ .dtype .kind == 'O' :
148+ raise
149+ tm .assert_almost_equal (targ .real , res .real )
150+ tm .assert_almost_equal (targ .imag , res .imag )
122151
123152 def check_fun_data (self , testfunc , targfunc ,
124153 testarval , targarval , targarnanval , ** kwargs ):
125- for axis in list (range (targarval .ndim )):
154+ for axis in list (range (targarval .ndim ))+ [ None ] :
126155 for skipna in [False , True ]:
127156 targartempval = targarval if skipna else targarnanval
128157 try :
@@ -215,6 +244,12 @@ def check_funs(self, testfunc, targfunc,
215244
216245 if allow_obj :
217246 self .arr_obj = np .vstack (objs )
247+ # some nanops handle object dtypes better than their numpy
248+ # counterparts, so the numpy functions need to be given something
249+ # else
250+ if allow_obj == 'convert' :
251+ targfunc = partial (self ._badobj_wrap ,
252+ func = targfunc , allow_complex = allow_complex )
218253 self .check_fun (testfunc , targfunc , 'arr_obj' , ** kwargs )
219254
220255 def check_funs_ddof (self , testfunc , targfunc ,
@@ -229,6 +264,14 @@ def check_funs_ddof(self, testfunc, targfunc,
229264 except BaseException as exc :
230265 exc .args += ('ddof %s' % ddof ,)
231266
267+ def _badobj_wrap (self , value , func , allow_complex = True , ** kwargs ):
268+ if value .dtype .kind == 'O' :
269+ if allow_complex :
270+ value = value .astype ('c16' )
271+ else :
272+ value = value .astype ('f8' )
273+ return func (value , ** kwargs )
274+
232275 def test_nanany (self ):
233276 self .check_funs (nanops .nanany , np .any ,
234277 allow_all_nan = False , allow_str = False , allow_date = False )
@@ -241,36 +284,15 @@ def test_nansum(self):
241284 self .check_funs (nanops .nansum , np .sum ,
242285 allow_str = False , allow_date = False )
243286
244- def _nanmean_wrap (self , value , * args , ** kwargs ):
245- dtype = value .dtype
246- res = nanops .nanmean (value , * args , ** kwargs )
247- if dtype .kind == 'O' :
248- res = np .round (res , decimals = 13 )
249- return res
250-
251- def _mean_wrap (self , value , * args , ** kwargs ):
252- dtype = value .dtype
253- if dtype .kind == 'O' :
254- value = value .astype ('c16' )
255- res = np .mean (value , * args , ** kwargs )
256- if dtype .kind == 'O' :
257- res = np .round (res , decimals = 13 )
258- return res
259-
260287 def test_nanmean (self ):
261- self .check_funs (self . _nanmean_wrap , self . _mean_wrap ,
288+ self .check_funs (nanops . nanmean , np . mean ,
262289 allow_complex = False , allow_obj = False ,
263290 allow_str = False , allow_date = False )
264291
265- def _median_wrap (self , value , * args , ** kwargs ):
266- if value .dtype .kind == 'O' :
267- value = value .astype ('c16' )
268- res = np .median (value , * args , ** kwargs )
269- return res
270-
271292 def test_nanmedian (self ):
272- self .check_funs (nanops .nanmedian , self ._median_wrap ,
273- allow_complex = False , allow_str = False , allow_date = False )
293+ self .check_funs (nanops .nanmedian , np .median ,
294+ allow_complex = False , allow_str = False , allow_date = False ,
295+ allow_obj = 'convert' )
274296
275297 def test_nanvar (self ):
276298 self .check_funs_ddof (nanops .nanvar , np .var ,
0 commit comments