go-chart/seq/sequence.go

260 lines
4.8 KiB
Go
Raw Normal View History

2017-05-12 17:17:43 -04:00
package seq
2016-07-29 21:24:25 -04:00
2017-05-02 01:18:52 -04:00
import (
"math"
"sort"
)
2017-05-12 17:17:43 -04:00
// New wraps a provider with a seq.
func New(provider Provider) Seq {
return Seq{Provider: provider}
}
// Values returns a new seq composed of a given set of values.
func Values(values ...float64) Seq {
2017-05-02 01:18:52 -04:00
return Seq{Provider: Array(values)}
}
2016-07-29 21:24:25 -04:00
2017-05-12 17:17:43 -04:00
// Provider is a provider for values for a seq.
2017-04-30 00:12:39 -04:00
type Provider interface {
2017-04-28 19:07:36 -04:00
Len() int
GetValue(int) float64
2016-07-29 21:24:25 -04:00
}
2017-05-12 17:17:43 -04:00
// Seq is a utility wrapper for seq providers.
2017-04-30 00:12:39 -04:00
type Seq struct {
Provider
2016-07-29 21:24:25 -04:00
}
2017-05-12 17:17:43 -04:00
// Array enumerates the seq into a slice.
2017-04-30 03:39:38 -04:00
func (s Seq) Array() (output []float64) {
2017-05-02 01:34:58 -04:00
if s.Len() == 0 {
return
}
2017-04-30 03:39:38 -04:00
output = make([]float64, s.Len())
for i := 0; i < s.Len(); i++ {
output[i] = s.GetValue(i)
}
return
}
2017-04-28 19:07:36 -04:00
// Each applies the `mapfn` to all values in the value provider.
2017-04-30 00:12:39 -04:00
func (s Seq) Each(mapfn func(int, float64)) {
2017-04-28 19:07:36 -04:00
for i := 0; i < s.Len(); i++ {
mapfn(i, s.GetValue(i))
2016-07-31 19:54:09 -04:00
}
}
2017-04-28 19:07:36 -04:00
// Map applies the `mapfn` to all values in the value provider,
2017-05-12 17:17:43 -04:00
// returning a new seq.
2017-04-30 00:12:39 -04:00
func (s Seq) Map(mapfn func(i int, v float64) float64) Seq {
2017-04-28 19:07:36 -04:00
output := make([]float64, s.Len())
for i := 0; i < s.Len(); i++ {
mapfn(i, s.GetValue(i))
2016-07-29 21:24:25 -04:00
}
2017-04-30 00:12:39 -04:00
return Seq{Array(output)}
2016-07-29 21:24:25 -04:00
}
2016-07-31 19:54:09 -04:00
2017-05-12 17:17:43 -04:00
// FoldLeft collapses a seq from left to right.
2017-04-30 00:12:39 -04:00
func (s Seq) FoldLeft(mapfn func(i int, v0, v float64) float64) (v0 float64) {
if s.Len() == 0 {
return 0
}
2017-04-30 02:17:28 -04:00
if s.Len() == 1 {
return s.GetValue(0)
}
2017-04-30 00:12:39 -04:00
v0 = s.GetValue(0)
for i := 1; i < s.Len(); i++ {
v0 = mapfn(i, v0, s.GetValue(i))
}
return
}
2017-05-12 17:17:43 -04:00
// FoldRight collapses a seq from right to left.
2017-04-30 00:12:39 -04:00
func (s Seq) FoldRight(mapfn func(i int, v0, v float64) float64) (v0 float64) {
if s.Len() == 0 {
return 0
}
2017-04-30 02:17:28 -04:00
if s.Len() == 1 {
return s.GetValue(0)
}
v0 = s.GetValue(s.Len() - 1)
for i := s.Len() - 2; i >= 0; i-- {
2017-04-30 00:12:39 -04:00
v0 = mapfn(i, v0, s.GetValue(i))
}
return
}
2017-05-12 17:17:43 -04:00
// Min returns the minimum value in the seq.
2017-05-02 01:18:52 -04:00
func (s Seq) Min() float64 {
if s.Len() == 0 {
return 0
}
min := s.GetValue(0)
var value float64
for i := 1; i < s.Len(); i++ {
value = s.GetValue(i)
if value < min {
min = value
}
}
return min
}
2017-05-12 17:17:43 -04:00
// Max returns the maximum value in the seq.
2017-05-02 01:18:52 -04:00
func (s Seq) Max() float64 {
if s.Len() == 0 {
return 0
}
max := s.GetValue(0)
var value float64
for i := 1; i < s.Len(); i++ {
value = s.GetValue(i)
if value > max {
max = value
}
}
return max
}
// MinMax returns the minimum and the maximum in one pass.
func (s Seq) MinMax() (min, max float64) {
if s.Len() == 0 {
return
}
min = s.GetValue(0)
max = min
var value float64
for i := 1; i < s.Len(); i++ {
value = s.GetValue(i)
if value < min {
min = value
}
if value > max {
max = value
}
}
return
}
2017-05-12 17:17:43 -04:00
// Sort returns the seq sorted in ascending order.
// This fully enumerates the seq.
2017-05-02 01:18:52 -04:00
func (s Seq) Sort() Seq {
if s.Len() == 0 {
return s
}
values := s.Array()
sort.Float64s(values)
return Seq{Provider: Array(values)}
}
2017-05-12 17:17:43 -04:00
// Median returns the median or middle value in the sorted seq.
2017-05-02 01:18:52 -04:00
func (s Seq) Median() (median float64) {
l := s.Len()
if l == 0 {
return
}
sorted := s.Sort()
if l%2 == 0 {
v0 := sorted.GetValue(l/2 - 1)
v1 := sorted.GetValue(l/2 + 1)
median = (v0 + v1) / 2
} else {
median = float64(sorted.GetValue(l << 1))
}
return
}
2017-04-30 00:12:39 -04:00
// Sum adds all the elements of a series together.
func (s Seq) Sum() (accum float64) {
2017-04-28 19:07:36 -04:00
if s.Len() == 0 {
return 0
2016-07-31 19:54:09 -04:00
}
2017-04-28 19:07:36 -04:00
for i := 0; i < s.Len(); i++ {
accum += s.GetValue(i)
2016-07-31 19:54:09 -04:00
}
2017-04-30 00:12:39 -04:00
return
}
// Average returns the float average of the values in the buffer.
func (s Seq) Average() float64 {
if s.Len() == 0 {
return 0
}
return s.Sum() / float64(s.Len())
2016-07-31 19:54:09 -04:00
}
2017-04-28 19:07:36 -04:00
// Variance computes the variance of the buffer.
2017-04-30 00:12:39 -04:00
func (s Seq) Variance() float64 {
2017-04-28 19:07:36 -04:00
if s.Len() == 0 {
return 0
2016-07-31 19:54:09 -04:00
}
2016-08-01 03:50:32 -04:00
2017-04-28 19:07:36 -04:00
m := s.Average()
var variance, v float64
for i := 0; i < s.Len(); i++ {
v = s.GetValue(i)
variance += (v - m) * (v - m)
2016-08-01 03:50:32 -04:00
}
2017-04-28 19:07:36 -04:00
return variance / float64(s.Len())
2016-08-01 03:50:32 -04:00
}
2017-02-28 20:55:48 -05:00
2017-04-28 19:07:36 -04:00
// StdDev returns the standard deviation.
2017-04-30 00:12:39 -04:00
func (s Seq) StdDev() float64 {
2017-04-28 19:07:36 -04:00
if s.Len() == 0 {
return 0
2017-02-28 20:55:48 -05:00
}
2017-04-28 19:07:36 -04:00
return math.Pow(s.Variance(), 0.5)
2017-02-28 20:55:48 -05:00
}
2017-05-02 01:18:52 -04:00
//Percentile finds the relative standing in a slice of floats.
// `percent` should be given on the interval [0,1.0).
func (s Seq) Percentile(percent float64) (percentile float64) {
l := s.Len()
if l == 0 {
return 0
}
if percent < 0 || percent > 1.0 {
panic("percent out of range [0.0, 1.0)")
}
sorted := s.Sort()
index := percent * float64(l)
if index == float64(int64(index)) {
i := f64i(index)
ci := sorted.GetValue(i - 1)
c := sorted.GetValue(i)
percentile = (ci + c) / 2.0
} else {
i := f64i(index)
percentile = sorted.GetValue(i)
}
return percentile
}
2017-05-02 01:34:58 -04:00
// Normalize maps every value to the interval [0, 1.0].
2017-05-02 01:18:52 -04:00
func (s Seq) Normalize() Seq {
min, max := s.MinMax()
delta := max - min
output := make([]float64, s.Len())
for i := 0; i < s.Len(); i++ {
output[i] = (s.GetValue(i) - min) / delta
}
return Seq{Provider: Array(output)}
}