go-ml.dev/pkg/base@v0.0.0-20200610162856-60c38abac71b/fu/rank.go (about)

     1  package fu
     2  
     3  import (
     4  	"math"
     5  	"sort"
     6  )
     7  
     8  type rankarr struct {
     9  	d []float32
    10  	n []int
    11  }
    12  
    13  func (a rankarr) Len() int {
    14  	return len(a.d)
    15  }
    16  func (a rankarr) Swap(i, j int) {
    17  	a.d[i], a.d[j] = a.d[j], a.d[i]
    18  	a.n[i], a.n[j] = a.n[j], a.n[i]
    19  }
    20  
    21  func (a rankarr) Less(i, j int) bool {
    22  	return a.d[i] < a.d[j]
    23  }
    24  
    25  func Rank(a []float32, first ...bool) []float32 {
    26  	r := make([]float32, len(a))
    27  	n := make([]int, len(a))
    28  	for i, v := range a {
    29  		r[i] = Round32(v, 4)
    30  		n[i] = i
    31  	}
    32  	sort.Stable(rankarr{r, n})
    33  	for i := 0; i < len(r); {
    34  		j := i
    35  		for i++; i < len(r) && r[j] == r[i]; i++ {
    36  		}
    37  		x := float32(j)
    38  		if !Fnzb(first...) {
    39  			x = float32(i-j)/2 + x
    40  		}
    41  		for ; j < i+1 && j < len(r); j++ {
    42  			r[j] = x
    43  		}
    44  	}
    45  	rank := make([]float32, len(a))
    46  	for i, j := range n {
    47  		rank[j] = r[i]
    48  	}
    49  	return rank
    50  }
    51  
    52  func RankPct(a []float32, first ...bool) []float32 {
    53  	rank := Rank(a, first...)
    54  	max := Maxr(float32(math.Inf(-1)), rank...)
    55  	for i, x := range rank {
    56  		rank[i] = x / max
    57  	}
    58  	return rank
    59  }