-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmath.go
103 lines (84 loc) · 1.83 KB
/
math.go
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
package hjem
import (
"fmt"
"math"
"time"
)
type Aggregation struct {
Mean int `json:"mean"`
Std int `json:"std"`
N int `json:"n"`
}
func AggregationFromPrices(prices []int) Aggregation {
var sum int
n := len(prices)
for _, p := range prices {
sum += p
}
mean := sum / n
var std float64
for _, p := range prices {
std += math.Pow(float64(p-mean), 2)
}
stdv := int(math.Sqrt(std / float64(n)))
return Aggregation{
Mean: mean,
Std: stdv,
N: n,
}
}
func SeperateOutliers(sales []*JSONSale, prices []int, aggr Aggregation, stdf int) ([]int, []*JSONSale) {
var normal []int
var outliers []*JSONSale
lowb, upperb := aggr.Mean+aggr.Std*-stdf, aggr.Mean+aggr.Std*stdf
for i, _ := range sales {
p := prices[i]
s := sales[i]
if p < lowb || p > upperb {
outliers = append(outliers, s)
continue
}
normal = append(normal, p)
}
return normal, outliers
}
func SalesStatistics(addrs []*Address, sales []*JSONSale, stdf int) ([]*JSONSale, map[time.Time]Aggregation) {
type G struct {
S []*JSONSale
P []int
}
temp := map[int]G{}
for _, s := range sales {
year, _, _ := s.When.Date()
sqMeters := addrs[s.AddrIndex].BoligaBuildingSize
if sqMeters == 0 {
continue
}
g := temp[year]
g.S = append(g.S, s)
g.P = append(g.P, s.Amount/sqMeters)
temp[year] = g
}
out := map[time.Time]Aggregation{}
outliers := map[*JSONSale]bool{}
for Y, g := range temp {
year, _ := time.Parse("2-1-2006", fmt.Sprintf("1-1-%d", Y))
agg := AggregationFromPrices(g.P)
if stdf > 0 {
_, outlz := SeperateOutliers(g.S, g.P, agg, stdf)
for _, ol := range outlz {
outliers[ol] = true
}
}
out[year] = agg
}
for i := 0; i < len(sales); i++ {
s := sales[i]
// primary index: 0
if outliers[s] && s.AddrIndex != 0 {
sales = append(sales[:i], sales[i+1:]...)
i--
}
}
return sales, out
}