gonum.org/v1/gonum@v0.14.0/stat/distuv/f_test.go (about)

     1  // Copyright ©2017 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package distuv
     6  
     7  import (
     8  	"math"
     9  	"sort"
    10  	"testing"
    11  
    12  	"golang.org/x/exp/rand"
    13  
    14  	"gonum.org/v1/gonum/floats/scalar"
    15  )
    16  
    17  func TestFProb(t *testing.T) {
    18  	t.Parallel()
    19  	for _, test := range []struct {
    20  		x, d1, d2, want float64
    21  	}{
    22  		// Values calculated with scipy.stats.f
    23  		{0.0001, 4, 6, 0.00053315559110558126},
    24  		{0.1, 1, 1, 0.91507658371794609},
    25  		{0.5, 11, 7, 0.66644660411410883},
    26  		{0.9, 20, 15, 0.88293424959522437},
    27  		{1, 1, 1, 0.15915494309189535},
    28  		{2, 15, 12, 0.16611971273429088},
    29  		{5, 4, 8, 0.013599775603702537},
    30  		{10, 12, 9, 0.00032922887567957289},
    31  		{100, 7, 7, 6.08037637806889e-08},
    32  		{1000, 2, 1, 1.1171959870312232e-05},
    33  	} {
    34  		pdf := F{test.d1, test.d2, nil}.Prob(test.x)
    35  		if !scalar.EqualWithinAbsOrRel(pdf, test.want, 1e-10, 1e-10) {
    36  			t.Errorf("Prob mismatch, x = %v, d1 = %v, d2 = %v. Got %v, want %v", test.x, test.d1, test.d2, pdf, test.want)
    37  		}
    38  	}
    39  }
    40  
    41  func TestFCDF(t *testing.T) {
    42  	t.Parallel()
    43  	for _, test := range []struct {
    44  		x, d1, d2, want float64
    45  	}{
    46  		// Values calculated with scipy.stats.f
    47  		{0.0001, 4, 6, 2.6660741629519019e-08},
    48  		{0.1, 1, 1, 0.19498222904213672},
    49  		{0.5, 11, 7, 0.14625028471336987},
    50  		{0.9, 20, 15, 0.40567939897287852},
    51  		{1, 1, 1, 0.50000000000000011},
    52  		{2, 15, 12, 0.8839384428956264},
    53  		{5, 4, 8, 0.97429642410900219},
    54  		{10, 12, 9, 0.99915733385467187},
    55  		{100, 7, 7, 0.99999823560259171},
    56  		{1000, 2, 1, 0.97764490829950534},
    57  	} {
    58  		cdf := F{test.d1, test.d2, nil}.CDF(test.x)
    59  		if !scalar.EqualWithinAbsOrRel(cdf, test.want, 1e-10, 1e-10) {
    60  			t.Errorf("CDF mismatch, x = %v, d1 = %v, d2 = %v. Got %v, want %v", test.x, test.d1, test.d2, cdf, test.want)
    61  		}
    62  	}
    63  }
    64  
    65  func TestF(t *testing.T) {
    66  	t.Parallel()
    67  	src := rand.New(rand.NewSource(1))
    68  	for i, f := range []F{
    69  		{13, 16, src},
    70  		{42, 31, src},
    71  		{77, 92, src},
    72  	} {
    73  		testF(t, f, i)
    74  	}
    75  }
    76  
    77  func testF(t *testing.T, f F, i int) {
    78  	const (
    79  		tol  = 1e-2
    80  		n    = 1e6
    81  		bins = 50
    82  	)
    83  	x := make([]float64, n)
    84  	generateSamples(x, f)
    85  	sort.Float64s(x)
    86  
    87  	testRandLogProbContinuous(t, i, 0, x, f, tol, bins)
    88  	checkProbContinuous(t, i, x, 0, math.Inf(1), f, 1e-4)
    89  	checkMean(t, i, x, f, tol)
    90  	checkVarAndStd(t, i, x, f, tol)
    91  	checkExKurtosis(t, i, x, f, 1e-1)
    92  	checkSkewness(t, i, x, f, 5e-2)
    93  	checkQuantileCDFSurvival(t, i, x, f, 5e-3)
    94  	checkMode(t, i, x, f, 2e-2, 3e-2)
    95  
    96  	if f.NumParameters() != 2 {
    97  		t.Errorf("Wrong number of parameters. Got %v, want 2", f.NumParameters())
    98  	}
    99  }
   100  
   101  func TestFUndefined(t *testing.T) {
   102  	t.Parallel()
   103  	for _, d1 := range []float64{1, 100} {
   104  		for _, d2 := range []float64{4, 8} {
   105  			f := F{d1, d2, nil}
   106  			exKurt := f.ExKurtosis()
   107  			if !math.IsNaN(exKurt) {
   108  				t.Errorf("Expected NaN excess kurtosis for D1 = %g and D2 = %g, got %v", d1, d2, exKurt)
   109  			}
   110  		}
   111  	}
   112  	for _, d1 := range []float64{1, 100} {
   113  		for _, d2 := range []float64{1, 2} {
   114  			f := F{d1, d2, nil}
   115  			mean := f.Mean()
   116  			if !math.IsNaN(mean) {
   117  				t.Errorf("Expected NaN mean for D1 = %g and D2 = %g, got %v", d1, d2, mean)
   118  			}
   119  		}
   120  	}
   121  	for _, d1 := range []float64{1, 2} {
   122  		for _, d2 := range []float64{1, 100} {
   123  			f := F{d1, d2, nil}
   124  			mode := f.Mode()
   125  			if !math.IsNaN(mode) {
   126  				t.Errorf("Expected NaN mode for D1 = %g and D2 = %g, got %v", d1, d2, mode)
   127  			}
   128  		}
   129  	}
   130  	for _, d1 := range []float64{1, 100} {
   131  		for _, d2 := range []float64{3, 6} {
   132  			f := F{d1, d2, nil}
   133  			skewness := f.Skewness()
   134  			if !math.IsNaN(skewness) {
   135  				t.Errorf("Expected NaN skewness for D1 = %g and D2 = %g, got %v", d1, d2, skewness)
   136  			}
   137  		}
   138  	}
   139  	for _, d1 := range []float64{1, 100} {
   140  		for _, d2 := range []float64{2, 4} {
   141  			f := F{d1, d2, nil}
   142  			variance := f.Variance()
   143  			if !math.IsNaN(variance) {
   144  				t.Errorf("Expected NaN variance for D1 = %g and D2 = %g, got %v", d1, d2, variance)
   145  			}
   146  			stdDev := f.StdDev()
   147  			if !math.IsNaN(stdDev) {
   148  				t.Errorf("Expected NaN standard deviation for D1 = %g and D2 = %g, got %v", d1, d2, variance)
   149  			}
   150  		}
   151  	}
   152  }