1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
|
package dstream
import (
"fmt"
"gonum.org/v1/gonum/floats"
)
type center struct {
source Dstream
// Positions of variables to center
pos []int
// Map from variable name to variable position
vpos map[string]int
// Query if something is in pos
cenpos map[int]int
// Means of variables to center
means []float64
}
func (c *center) Close() {
c.source.Close()
}
func (c *center) Reset() {
c.source.Reset()
}
// Center returns a new Dstream in which the given columns have been
// mean-centered. Currently only works with float64 type data.
func Center(source Dstream, names ...string) Dstream {
means := make([]float64, len(names))
// Map from variable names to position
vpos := make(map[string]int)
for k, na := range source.Names() {
vpos[na] = k
}
// Positions of variables to center. cenpos[j], if it exists,
// is the position within means where the mean of the variable
// j is found. If cenpos[j] does not exist, the variable
// should not be centered.
var pos []int
cenpos := make(map[int]int)
for j, na := range names {
q, ok := vpos[na]
if !ok {
msg := fmt.Sprintf("Center: variable '%s' not found.\n", na)
panic(msg)
}
pos = append(pos, q)
cenpos[q] = j
}
// Get the means of the variables to center
source.Reset()
n := 0
for source.Next() {
for i, j := range pos {
v := source.GetPos(j).([]float64)
if i == 0 {
n += len(v)
}
means[i] += floats.Sum(v)
}
}
floats.Scale(1/float64(n), means)
return ¢er{
source: source,
pos: pos,
means: means,
cenpos: cenpos,
vpos: vpos,
}
}
func (c *center) GetPos(j int) interface{} {
x := c.source.GetPos(j).([]float64)
q, ok := c.cenpos[j]
if !ok {
return x
}
m := c.means[q]
z := make([]float64, len(x))
for i := range x {
z[i] = x[i] - m
}
return z
}
func (c *center) Names() []string {
return c.source.Names()
}
func (c *center) Next() bool {
return c.source.Next()
}
func (c *center) NumObs() int {
return c.source.NumObs()
}
func (c *center) NumVar() int {
return c.source.NumVar()
}
func (c *center) Get(na string) interface{} {
return c.GetPos(c.vpos[na])
}
|