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