mirror of
https://github.com/gonum/gonum.git
synced 2025-10-19 05:24:52 +08:00
use two pass correction in correlation
This commit is contained in:
44
stat.go
44
stat.go
@@ -132,25 +132,22 @@ func ChiSquare(obs, exp []float64) float64 {
|
|||||||
func Correlation(x, y, weights []float64) float64 {
|
func Correlation(x, y, weights []float64) float64 {
|
||||||
// same implementation as Covariance
|
// same implementation as Covariance
|
||||||
|
|
||||||
// don't have a paper for this, but the unweighted adaptation seems natural.
|
// This is a two-pass corrected implementation.
|
||||||
// The weighted version doesn't perform a correction. It seemed like the
|
// don't have a paper for this, but the adaptation seems natural.
|
||||||
// performance would suffer too much.
|
|
||||||
|
|
||||||
if len(x) != len(y) {
|
if len(x) != len(y) {
|
||||||
panic("stat: slice length mismatch")
|
panic("stat: slice length mismatch")
|
||||||
}
|
}
|
||||||
xu := Mean(x, weights)
|
xu := Mean(x, weights)
|
||||||
yu := Mean(y, weights)
|
yu := Mean(y, weights)
|
||||||
|
var (
|
||||||
|
sxx float64
|
||||||
|
syy float64
|
||||||
|
sxy float64
|
||||||
|
xcompensation float64
|
||||||
|
ycompensation float64
|
||||||
|
)
|
||||||
if weights == nil {
|
if weights == nil {
|
||||||
var (
|
|
||||||
sxx float64
|
|
||||||
syy float64
|
|
||||||
sxy float64
|
|
||||||
xcompensation float64
|
|
||||||
ycompensation float64
|
|
||||||
)
|
|
||||||
|
|
||||||
for i, xv := range x {
|
for i, xv := range x {
|
||||||
yv := y[i]
|
yv := y[i]
|
||||||
xd := xv - xu
|
xd := xv - xu
|
||||||
@@ -165,24 +162,25 @@ func Correlation(x, y, weights []float64) float64 {
|
|||||||
syy -= ycompensation * ycompensation / float64(len(x))
|
syy -= ycompensation * ycompensation / float64(len(x))
|
||||||
return (sxy - xcompensation*ycompensation/float64(len(x))) / math.Sqrt(sxx*syy)
|
return (sxy - xcompensation*ycompensation/float64(len(x))) / math.Sqrt(sxx*syy)
|
||||||
}
|
}
|
||||||
var (
|
|
||||||
sxx float64
|
var sumWeights float64
|
||||||
syy float64
|
|
||||||
sxy float64
|
|
||||||
sumWeights float64
|
|
||||||
)
|
|
||||||
|
|
||||||
for i, xv := range x {
|
for i, xv := range x {
|
||||||
w := weights[i]
|
w := weights[i]
|
||||||
yv := y[i]
|
yv := y[i]
|
||||||
xd := xv - xu
|
xd := xv - xu
|
||||||
|
wxd := w * xd
|
||||||
yd := yv - yu
|
yd := yv - yu
|
||||||
sxx += w * xd * xd
|
wyd := w * yd
|
||||||
syy += w * yd * yd
|
sxx += wxd * xd
|
||||||
sxy += w * xd * yd
|
syy += wyd * yd
|
||||||
|
sxy += wxd * yd
|
||||||
|
xcompensation += wxd
|
||||||
|
ycompensation += wyd
|
||||||
sumWeights += w
|
sumWeights += w
|
||||||
}
|
}
|
||||||
return sxy / math.Sqrt(sxx*syy)
|
sxx -= xcompensation * xcompensation / sumWeights
|
||||||
|
syy -= ycompensation * ycompensation / sumWeights
|
||||||
|
return (sxy - xcompensation * ycompensation / sumWeights) / math.Sqrt(sxx*syy)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Covariance returns the weighted covariance between the samples of x and y.
|
// Covariance returns the weighted covariance between the samples of x and y.
|
||||||
|
Reference in New Issue
Block a user