13
13
14
14
class TestnanopsDataFrame (tm .TestCase ):
15
15
def setUp (self ):
16
+ np .random .seed (11235 )
17
+
16
18
self .arr_shape = (11 , 7 , 5 )
17
19
18
20
self .arr_float = np .random .randn (* self .arr_shape )
@@ -118,11 +120,38 @@ def check_results(self, targ, res, axis):
118
120
res = getattr (res , 'values' , res )
119
121
if axis != 0 and hasattr (targ , 'shape' ) and targ .ndim :
120
122
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 )
122
151
123
152
def check_fun_data (self , testfunc , targfunc ,
124
153
testarval , targarval , targarnanval , ** kwargs ):
125
- for axis in list (range (targarval .ndim )):
154
+ for axis in list (range (targarval .ndim ))+ [ None ] :
126
155
for skipna in [False , True ]:
127
156
targartempval = targarval if skipna else targarnanval
128
157
try :
@@ -215,6 +244,12 @@ def check_funs(self, testfunc, targfunc,
215
244
216
245
if allow_obj :
217
246
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 )
218
253
self .check_fun (testfunc , targfunc , 'arr_obj' , ** kwargs )
219
254
220
255
def check_funs_ddof (self , testfunc , targfunc ,
@@ -229,6 +264,14 @@ def check_funs_ddof(self, testfunc, targfunc,
229
264
except BaseException as exc :
230
265
exc .args += ('ddof %s' % ddof ,)
231
266
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
+
232
275
def test_nanany (self ):
233
276
self .check_funs (nanops .nanany , np .any ,
234
277
allow_all_nan = False , allow_str = False , allow_date = False )
@@ -241,36 +284,15 @@ def test_nansum(self):
241
284
self .check_funs (nanops .nansum , np .sum ,
242
285
allow_str = False , allow_date = False )
243
286
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
-
260
287
def test_nanmean (self ):
261
- self .check_funs (self . _nanmean_wrap , self . _mean_wrap ,
288
+ self .check_funs (nanops . nanmean , np . mean ,
262
289
allow_complex = False , allow_obj = False ,
263
290
allow_str = False , allow_date = False )
264
291
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
-
271
292
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' )
274
296
275
297
def test_nanvar (self ):
276
298
self .check_funs_ddof (nanops .nanvar , np .var ,
0 commit comments