Add weighting to KendallCorrelation
MODIFY
stat/stat.go
stat/stat.go
@@ -220,17 +220,18 @@ func Correlation(x, y, weights []float64) float64 {
// KendallCorrelation returns the weighted Kendall correlation between the
// samples of x and y.
// The lengths of x and y must be equal.
-func KendallCorrelation(x, y []float64) float64 {
+func KendallCorrelation(x, y, weights []float64) float64 {
if len(x) != len(y) {
panic("stat: slice length mismatch")
}
var (
- cc int // number of concordant pairs
- dc int // number of discordant pairs
+ cc float64 // number of concordant pairs
+ dc float64 // number of discordant pairs
n = len(x)
)
+ if weights == nil {
for i := 0; i < n; i++ {
for j := i; j < n; j++ {
if i == j {
@@ -243,7 +244,29 @@ func KendallCorrelation(x, y []float64) float64 {
}
}
}
- return float64(cc-dc) / float64(n*(n-1)/2)
+ return (cc - dc) / float64(n*(n-1)/2)
+ }
+
+ var sumWeights float64
+
+ var c int
+
+ for i := 0; i < n; i++ {
+ for j := i; j < n; j++ {
+ if i == j {
+ continue
+ }
+ c++
+ var weight = weights[i] * weights[j]
+ if math.Signbit(x[j]-x[i]) == math.Signbit(y[j]-y[i]) {
+ cc += weight
+ } else {
+ dc += weight
+ }
+ sumWeights += weight
+ }
+ }
+ return float64(cc-dc) / sumWeights
}
// Covariance returns the weighted covariance between the samples of x and y.

MODIFY
stat/stat_test.go
stat/stat_test.go
@@ -139,53 +139,77 @@ func TestCorrelation(t *testing.T) {
func ExampleKendallCorrelation() {
x := []float64{8, -3, 7, 8, -4}
y := []float64{10, 5, 6, 3, -1}
+ w := []float64{2, 1.5, 3, 3, 2}
fmt.Println("Kendall correlation computes the number of ordered pairs")
fmt.Println("between two datasets.")
- c := KendallCorrelation(x, y)
+ c := KendallCorrelation(x, y, w)
fmt.Printf("Kendall correlation is %.5f\n", c)
// Output:
// Kendall correlation computes the number of ordered pairs
// between two datasets.
- // Kendall correlation is 0.40000
+ // Kendall correlation is 0.25000
}
func TestKendallCorrelation(t *testing.T) {
for i, test := range []struct {
x []float64
y []float64
+ weights []float64
ans float64
}{
{
x: []float64{0, 1, 2, 3},
y: []float64{0, 1, 2, 3},
+ weights: nil,
ans: 1,
},
{
x: []float64{0, 1},
y: []float64{1, 0},
+ weights: nil,
ans: -1,
},
{
x: []float64{8, -3, 7, 8, -4},
y: []float64{10, 15, 4, 5, -1},
+ weights: nil,
ans: 0.2,
},
{
x: []float64{8, -3, 7, 8, -4},
y: []float64{10, 5, 6, 3, -1},
+ weights: nil,
ans: 0.4,
},
+ {
+ x: []float64{1, 2, 3, 4, 5},
+ y: []float64{2, 3, 4, 5, 6},
+ weights: []float64{1, 1, 1, 1, 1},
+ ans: 1,
+ },
+ {
+ x: []float64{1, 2, 3, 2, 1},
+ y: []float64{2, 3, 2, 1, 0},
+ weights: []float64{1, 1, 0, 0, 0},
+ ans: 1,
+ },
} {
- c := KendallCorrelation(test.x, test.y)
+ c := KendallCorrelation(test.x, test.y, test.weights)
if math.Abs(test.ans-c) > 1e-14 {
t.Errorf("Correlation mismatch case %d. Expected %v, Found %v", i, test.ans, c)
}
}
- if !panics(func() { KendallCorrelation(make([]float64, 2), make([]float64, 3)) }) {
- t.Errorf("Correlation did not panic with length mismatch")
+ if !panics(func() { KendallCorrelation(make([]float64, 2), make([]float64, 3), make([]float64, 3)) }) {
+ t.Errorf("KendallCorrelation did not panic with length mismatch")
+ }
+ if !panics(func() { KendallCorrelation(make([]float64, 2), make([]float64, 3), nil) }) {
+ t.Errorf("KendallCorrelation did not panic with length mismatch")
+ }
+ if !panics(func() { KendallCorrelation(make([]float64, 3), make([]float64, 3), make([]float64, 2)) }) {
+ t.Errorf("KendallCorrelation did not panic with weights length mismatch")
}
}

Add weighting to KendallCorrelation