You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
80 lines
1.7 KiB
80 lines
1.7 KiB
package stats |
|
|
|
import "math" |
|
|
|
// Percentile finds the relative standing in a slice of floats |
|
func Percentile(input Float64Data, percent float64) (percentile float64, err error) { |
|
|
|
if input.Len() == 0 { |
|
return math.NaN(), EmptyInput |
|
} |
|
|
|
if percent <= 0 || percent > 100 { |
|
return math.NaN(), BoundsErr |
|
} |
|
|
|
// Start by sorting a copy of the slice |
|
c := sortedCopy(input) |
|
|
|
// Multiply percent by length of input |
|
index := (percent / 100) * float64(len(c)) |
|
|
|
// Check if the index is a whole number |
|
if index == float64(int64(index)) { |
|
|
|
// Convert float to int |
|
i := int(index) |
|
|
|
// Find the value at the index |
|
percentile = c[i-1] |
|
|
|
} else if index > 1 { |
|
|
|
// Convert float to int via truncation |
|
i := int(index) |
|
|
|
// Find the average of the index and following values |
|
percentile, _ = Mean(Float64Data{c[i-1], c[i]}) |
|
|
|
} else { |
|
return math.NaN(), BoundsErr |
|
} |
|
|
|
return percentile, nil |
|
|
|
} |
|
|
|
// PercentileNearestRank finds the relative standing in a slice of floats using the Nearest Rank method |
|
func PercentileNearestRank(input Float64Data, percent float64) (percentile float64, err error) { |
|
|
|
// Find the length of items in the slice |
|
il := input.Len() |
|
|
|
// Return an error for empty slices |
|
if il == 0 { |
|
return math.NaN(), EmptyInput |
|
} |
|
|
|
// Return error for less than 0 or greater than 100 percentages |
|
if percent < 0 || percent > 100 { |
|
return math.NaN(), BoundsErr |
|
} |
|
|
|
// Start by sorting a copy of the slice |
|
c := sortedCopy(input) |
|
|
|
// Return the last item |
|
if percent == 100.0 { |
|
return c[il-1], nil |
|
} |
|
|
|
// Find ordinal ranking |
|
or := int(math.Ceil(float64(il) * percent / 100)) |
|
|
|
// Return the item that is in the place of the ordinal rank |
|
if or == 0 { |
|
return c[0], nil |
|
} |
|
return c[or-1], nil |
|
|
|
}
|
|
|