Skip to content

Instantly share code, notes, and snippets.

@zaltoprofen
Created October 26, 2016 12:24
Show Gist options
  • Save zaltoprofen/dc8a67fda73c81c431fd34948a972234 to your computer and use it in GitHub Desktop.
Save zaltoprofen/dc8a67fda73c81c431fd34948a972234 to your computer and use it in GitHub Desktop.
package main
import (
"errors"
"fmt"
"math/rand"
"sort"
"time"
)
func must(g float64, err error) float64 {
if err != nil {
panic(err)
}
return g
}
func main() {
rand.Seed(time.Now().UnixNano())
data := make([]float64, 1000000)
for i := range data {
data[i] = rand.NormFloat64()
data[i] *= data[i]
}
fmt.Println("Gini:", must(Gini(data)))
}
func Gini(data []float64) (float64, error) {
if len(data) < 2 {
return 0, errors.New("len(data) must be larger than 2")
}
var sum float64
for _, datum := range data {
if datum < 0 {
return 0, errors.New("data must have non-negative values")
}
sum += datum
}
sort.Sort(sort.Float64Slice(data))
data[0] /= sum
for i := 1; i < len(data); i++ {
data[i] /= sum
data[i] += data[i-1]
}
x := make([]float64, len(data))
for i := range x {
x[i] = float64(i+1) * 1.0 / float64(len(data))
}
y := data
var prevX, prevY float64
var S float64
for i := range y {
S += (x[i] - prevX) * (y[i] + prevY) / 2.0
prevX = x[i]
prevY = y[i]
}
return 1.0 - 2.0*S, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment