示例#1
0
// Slices the data into sections, returning a slice of float64s.
// Returns an error if the data set is empty.
func (q Quartile) Transform(analyzer *mino.Analyzer, data mino.Collection) (interface{}, error) {
	sections := q.Sections
	if sections == 0 {
		sections = 4
	}
	results := make([]float64, sections-1)
	dividend := (1 + data.Weight()) / float64(sections)

	// todo(connor4312): my algorithm below behaves oddly when the data
	// size is less than the number of requested sections. Whoever discovers
	// a solution to it is awarded three cookies.
	if data.Len() < sections {
		return results, InsufficientDataError
	}

	data.Sort(func(a, b mino.DataPoint) bool {
		return a.Value < b.Value
	})

	var weight float64
	var prev mino.DataPoint

SECTION:
	for i := 1; i < sections; i++ {
		target := float64(i) * dividend
		for data.HasMore() {
			current := data.Next()
			last := prev
			prev = current

			if weight+current.Weight > target {
				frac := (target - weight) / current.Weight
				results[i-1] = last.Value*(1-frac) + current.Value*frac
				data.Rewind(1)
				continue SECTION
			}

			weight += current.Weight
		}

		results[i-1] = prev.Value
	}

	return results, nil
}