@@ -186,13 +186,13 @@ def check_fun_data(self, testfunc, targfunc,
186
186
** kwargs )
187
187
self .check_results (targ , res , axis )
188
188
if skipna :
189
- res = testfunc (testarval , axis = axis )
189
+ res = testfunc (testarval , axis = axis , ** kwargs )
190
190
self .check_results (targ , res , axis )
191
191
if axis is None :
192
- res = testfunc (testarval , skipna = skipna )
192
+ res = testfunc (testarval , skipna = skipna , ** kwargs )
193
193
self .check_results (targ , res , axis )
194
194
if skipna and axis is None :
195
- res = testfunc (testarval )
195
+ res = testfunc (testarval , ** kwargs )
196
196
self .check_results (targ , res , axis )
197
197
except BaseException as exc :
198
198
exc .args += ('axis: %s of %s' % (axis , testarval .ndim - 1 ),
@@ -295,12 +295,13 @@ def check_funs_ddof(self, testfunc, targfunc,
295
295
allow_date = False , allow_tdelta = False , allow_obj = True ,):
296
296
for ddof in range (3 ):
297
297
try :
298
- self .check_funs (self , testfunc , targfunc ,
298
+ self .check_funs (testfunc , targfunc ,
299
299
allow_complex , allow_all_nan , allow_str ,
300
300
allow_date , allow_tdelta , allow_obj ,
301
301
ddof = ddof )
302
302
except BaseException as exc :
303
303
exc .args += ('ddof %s' % ddof ,)
304
+ raise
304
305
305
306
def _badobj_wrap (self , value , func , allow_complex = True , ** kwargs ):
306
307
if value .dtype .kind == 'O' :
@@ -370,16 +371,29 @@ def test_nanmedian(self):
370
371
371
372
def test_nanvar (self ):
372
373
self .check_funs_ddof (nanops .nanvar , np .var ,
373
- allow_complex = False , allow_date = False , allow_tdelta = False )
374
+ allow_complex = False ,
375
+ allow_str = False ,
376
+ allow_date = False ,
377
+ allow_tdelta = True ,
378
+ allow_obj = 'convert' )
374
379
375
380
def test_nanstd (self ):
376
381
self .check_funs_ddof (nanops .nanstd , np .std ,
377
- allow_complex = False , allow_date = False , allow_tdelta = True )
382
+ allow_complex = False ,
383
+ allow_str = False ,
384
+ allow_date = False ,
385
+ allow_tdelta = True ,
386
+ allow_obj = 'convert' )
378
387
379
388
def test_nansem (self ):
380
389
tm .skip_if_no_package ('scipy.stats' )
381
- self .check_funs_ddof (nanops .nansem , np .var ,
382
- allow_complex = False , allow_date = False , allow_tdelta = False )
390
+ from scipy .stats import sem
391
+ self .check_funs_ddof (nanops .nansem , sem ,
392
+ allow_complex = False ,
393
+ allow_str = False ,
394
+ allow_date = False ,
395
+ allow_tdelta = True ,
396
+ allow_obj = 'convert' )
383
397
384
398
def _minmax_wrap (self , value , axis = None , func = None ):
385
399
res = func (value , axis )
@@ -821,6 +835,123 @@ def test_non_convertable_values(self):
821
835
lambda : nanops ._ensure_numeric ([]))
822
836
823
837
838
+ class TestNanvarFixedValues (tm .TestCase ):
839
+
840
+ # xref GH10242
841
+
842
+ def setUp (self ):
843
+ # Samples from a normal distribution.
844
+ self .variance = variance = 3.0
845
+ self .samples = self .prng .normal (scale = variance ** 0.5 , size = 100000 )
846
+
847
+ def test_nanvar_all_finite (self ):
848
+ samples = self .samples
849
+ actual_variance = nanops .nanvar (samples )
850
+ np .testing .assert_almost_equal (
851
+ actual_variance , self .variance , decimal = 2 )
852
+
853
+ def test_nanvar_nans (self ):
854
+ samples = np .nan * np .ones (2 * self .samples .shape [0 ])
855
+ samples [::2 ] = self .samples
856
+
857
+ actual_variance = nanops .nanvar (samples , skipna = True )
858
+ np .testing .assert_almost_equal (
859
+ actual_variance , self .variance , decimal = 2 )
860
+
861
+ actual_variance = nanops .nanvar (samples , skipna = False )
862
+ np .testing .assert_almost_equal (
863
+ actual_variance , np .nan , decimal = 2 )
864
+
865
+ def test_nanstd_nans (self ):
866
+ samples = np .nan * np .ones (2 * self .samples .shape [0 ])
867
+ samples [::2 ] = self .samples
868
+
869
+ actual_std = nanops .nanstd (samples , skipna = True )
870
+ np .testing .assert_almost_equal (
871
+ actual_std , self .variance ** 0.5 , decimal = 2 )
872
+
873
+ actual_std = nanops .nanvar (samples , skipna = False )
874
+ np .testing .assert_almost_equal (
875
+ actual_std , np .nan , decimal = 2 )
876
+
877
+ def test_nanvar_axis (self ):
878
+ # Generate some sample data.
879
+ samples_norm = self .samples
880
+ samples_unif = self .prng .uniform (size = samples_norm .shape [0 ])
881
+ samples = np .vstack ([samples_norm , samples_unif ])
882
+
883
+ actual_variance = nanops .nanvar (samples , axis = 1 )
884
+ np .testing .assert_array_almost_equal (
885
+ actual_variance , np .array ([self .variance , 1.0 / 12 ]), decimal = 2 )
886
+
887
+ def test_nanvar_ddof (self ):
888
+ n = 5
889
+ samples = self .prng .uniform (size = (10000 , n + 1 ))
890
+ samples [:, - 1 ] = np .nan # Force use of our own algorithm.
891
+
892
+ variance_0 = nanops .nanvar (samples , axis = 1 , skipna = True , ddof = 0 ).mean ()
893
+ variance_1 = nanops .nanvar (samples , axis = 1 , skipna = True , ddof = 1 ).mean ()
894
+ variance_2 = nanops .nanvar (samples , axis = 1 , skipna = True , ddof = 2 ).mean ()
895
+
896
+ # The unbiased estimate.
897
+ var = 1.0 / 12
898
+ np .testing .assert_almost_equal (variance_1 , var , decimal = 2 )
899
+ # The underestimated variance.
900
+ np .testing .assert_almost_equal (
901
+ variance_0 , (n - 1.0 ) / n * var , decimal = 2 )
902
+ # The overestimated variance.
903
+ np .testing .assert_almost_equal (
904
+ variance_2 , (n - 1.0 ) / (n - 2.0 ) * var , decimal = 2 )
905
+
906
+ def test_ground_truth (self ):
907
+ # Test against values that were precomputed with Numpy.
908
+ samples = np .empty ((4 , 4 ))
909
+ samples [:3 , :3 ] = np .array ([[0.97303362 , 0.21869576 , 0.55560287 ],
910
+ [0.72980153 , 0.03109364 , 0.99155171 ],
911
+ [0.09317602 , 0.60078248 , 0.15871292 ]])
912
+ samples [3 ] = samples [:, 3 ] = np .nan
913
+
914
+ # Actual variances along axis=0, 1 for ddof=0, 1, 2
915
+ variance = np .array (
916
+ [[[0.13762259 , 0.05619224 , 0.11568816 ],
917
+ [0.20643388 , 0.08428837 , 0.17353224 ],
918
+ [0.41286776 , 0.16857673 , 0.34706449 ]],
919
+ [[0.09519783 , 0.16435395 , 0.05082054 ],
920
+ [0.14279674 , 0.24653093 , 0.07623082 ],
921
+ [0.28559348 , 0.49306186 , 0.15246163 ]]]
922
+ )
923
+
924
+ # Test nanvar.
925
+ for axis in range (2 ):
926
+ for ddof in range (3 ):
927
+ var = nanops .nanvar (samples , skipna = True , axis = axis , ddof = ddof )
928
+ np .testing .assert_array_almost_equal (
929
+ var [:3 ], variance [axis , ddof ]
930
+ )
931
+ np .testing .assert_equal (var [3 ], np .nan )
932
+
933
+ # Test nanstd.
934
+ for axis in range (2 ):
935
+ for ddof in range (3 ):
936
+ std = nanops .nanstd (samples , skipna = True , axis = axis , ddof = ddof )
937
+ np .testing .assert_array_almost_equal (
938
+ std [:3 ], variance [axis , ddof ] ** 0.5
939
+ )
940
+ np .testing .assert_equal (std [3 ], np .nan )
941
+
942
+ def test_nanstd_roundoff (self ):
943
+ # Regression test for GH 10242 (test data taken from GH 10489). Ensure
944
+ # that variance is stable.
945
+ data = Series (766897346 * np .ones (10 ))
946
+ for ddof in range (3 ):
947
+ result = data .std (ddof = ddof )
948
+ self .assertEqual (result , 0.0 )
949
+
950
+ @property
951
+ def prng (self ):
952
+ return np .random .RandomState (1234 )
953
+
954
+
824
955
if __name__ == '__main__' :
825
956
import nose
826
957
nose .runmodule (argv = [__file__ , '-vvs' , '-x' , '--pdb' , '--pdb-failure' ,
0 commit comments