poohbar
04/12/2022, 8:50 PMhfhbd
04/12/2022, 9:22 PMimport kotlinx.serialization.*
import kotlin.js.*
import kotlin.math.*
@Serializable
data class Stats(
val name: String,
val count: Int,
val min: Double,
val max: Double,
val median: Double,
val average: Double,
val std: Double,
val variance: Double,
val lowerQuantile: Double,
val upperQuantile: Double,
val uniqueValues: List<Double>?,
val iqr: Double,
val whiskerLength: Double,
val lowerWhisker: Double?,
val upperWhisker: Double?,
@Transient
val lowerExtrema: List<Double>? = null,
@Transient
val upperExtrema: List<Double>? = null
) {
companion object {
@JsName("createSelector")
operator fun <T> invoke(
name: String,
values: Iterable<T>,
whiskerLength: Double = 1.5,
selector: (T) -> Double
): Stats? = invoke(sortedValues = values.map(selector).sorted(), whiskerLength = whiskerLength, name = name)
@JsName("create")
operator fun invoke(name: String, sortedValues: List<Double>, whiskerLength: Double = 1.5): Stats? {
val count = sortedValues.size
if (count == 0) {
return null
}
val min: Double = sortedValues.minOrNull()!!
val max: Double = sortedValues.maxOrNull()!!
val median: Double = sortedValues[sortedValues.size / 2]
val average: Double = sortedValues.average()
val variance = sortedValues.sumOf { (it - average).pow(2) } / count
val std = sqrt(variance)
val lowerQuantile: Double = sortedValues[(sortedValues.size * 0.25).toInt()]
val upperQuantile: Double = sortedValues[(sortedValues.size * 0.75).toInt()]
val iqr = upperQuantile - lowerQuantile
val lowerWhisker = (lowerQuantile - whiskerLength * iqr).let {
if (min >= it) {
max(min, it)
} else {
sortedValues.takeLastWhile { v -> v > it }.firstOrNull()
}
}
val upperWhisker = (upperQuantile + whiskerLength * iqr).let {
if (max <= it) {
min(max, it)
} else {
sortedValues.takeWhile { v -> v <= it }.lastOrNull()
}
}
val lowerExtrema =
lowerWhisker?.let { sortedValues.takeWhile { it < lowerWhisker } }
val upperExtrema = upperWhisker?.let {
sortedValues.takeLastWhile { it > upperWhisker }
}
val uniqueValues = sortedValues.distinct().takeIf { it.size <= 15 }
return Stats(
name = name,
count = count,
min = min, max = max,
median = median,
average = average,
variance = variance,
std = std,
lowerQuantile = lowerQuantile,
upperQuantile = upperQuantile,
iqr = iqr,
whiskerLength = whiskerLength,
lowerWhisker = lowerWhisker,
upperWhisker = upperWhisker,
lowerExtrema = lowerExtrema,
upperExtrema = upperExtrema,
uniqueValues = uniqueValues
)
}
}
}
max
, min
, count
(for avg
) variables.Michael de Kaste
04/12/2022, 9:55 PMyourList.stream().collect(Collectors.summarizingLong(Long::longValue));
LongSummaryStatistics for range 1-5
Count: 5
Avg: 3.0
Min: 1
Max: 5
Sum: 15
Paul Griffith
04/12/2022, 11:08 PMfun Iterable<Int>.statistics(): IntSummaryStatistics {
return fold(IntSummaryStatistics()) { statistics, next ->
statistics.accept(next)
statistics
}
}
Klitos Kyriacou
04/13/2022, 7:59 AMMichael de Kaste
04/13/2022, 8:04 AM