org.nield.kotlinstatistics.FloatStatistics.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-statistics Show documentation
Show all versions of kotlin-statistics Show documentation
Statistical and analytical extensions for Kotlin
The newest version!
import org.apache.commons.math3.stat.StatUtils
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics
import org.nield.kotlinstatistics.*
import org.nield.kotlinstatistics.range.Range
import org.nield.kotlinstatistics.range.until
import java.math.BigDecimal
import java.util.concurrent.atomic.AtomicBoolean
val FloatArray.descriptiveStatistics get(): Descriptives = DescriptiveStatistics().apply { forEach { addValue(it.toDouble()) } }.let(::ApacheDescriptives)
fun FloatArray.geometricMean() = asSequence().geometricMean()
fun FloatArray.median() = percentile(50.0)
fun FloatArray.percentile(percentile: Double) = asSequence().percentile(50.0)
fun FloatArray.variance() = asSequence().variance()
fun FloatArray.sumOfSquares() = asSequence().sumOfSquares()
fun FloatArray.standardDeviation() = asSequence().standardDeviation()
fun FloatArray.normalize() = StatUtils.normalize(asSequence().map { it.toDouble() }.toList().toDoubleArray())
val FloatArray.kurtosis get() = descriptiveStatistics.kurtosis
val FloatArray.skewness get() = descriptiveStatistics.skewness
// AGGREGATION OPERATORS
inline fun Sequence.sumBy(crossinline keySelector: (T) -> K, crossinline floatSelector: (T) -> Float) =
groupApply(keySelector, floatSelector) { it.sum() }
inline fun Iterable.sumBy(crossinline keySelector: (T) -> K, crossinline floatSelector: (T) -> Float) =
asSequence().sumBy(keySelector, floatSelector)
fun Sequence>.sumBy() =
groupApply({it.first}, {it.second}) { it.sum() }
fun Iterable>.sumBy() = asSequence().sumBy()
inline fun Sequence.averageBy(crossinline keySelector: (T) -> K, crossinline floatSelector: (T) -> Float) =
groupApply(keySelector, floatSelector) { it.average() }
inline fun Iterable.averageBy(crossinline keySelector: (T) -> K, crossinline floatSelector: (T) -> Float) =
asSequence().averageBy(keySelector, floatSelector)
fun Sequence>.averageBy() =
groupApply({it.first}, {it.second}) { it.average() }
fun Iterable>.averageBy() = asSequence().averageBy()
fun Sequence.floatRange() = toList().floatRange()
fun Iterable.floatRange() = toList().let { (it.min()?:throw Exception("At least one element must be present"))..(it.max()?:throw Exception("At least one element must be present")) }
inline fun Sequence.floatRangeBy(crossinline keySelector: (T) -> K, crossinline floatSelector: (T) -> Float) =
groupApply(keySelector, floatSelector) { it.range() }
inline fun Iterable.floatRangeBy(crossinline keySelector: (T) -> K, crossinline floatSelector: (T) -> Float) =
asSequence().rangeBy(keySelector, floatSelector)
// Bin Operators
inline fun Sequence.binByFloat(binSize: Float,
crossinline valueSelector: (T) -> Float,
rangeStart: Float? = null
): BinModel, Float> = toList().binByFloat(binSize, valueSelector, { it }, rangeStart)
inline fun Sequence.binByFloat(binSize: Float,
crossinline valueSelector: (T) -> Float,
crossinline groupOp: (List) -> G,
rangeStart: Float? = null
): BinModel = toList().binByFloat(binSize, valueSelector, groupOp, rangeStart)
inline fun Iterable.binByFloat(binSize: Float,
crossinline valueSelector: (T) -> Float,
rangeStart: Float? = null
): BinModel, Float> = toList().binByFloat(binSize, valueSelector, { it }, rangeStart)
inline fun Iterable.binByFloat(binSize: Float,
crossinline valueSelector: (T) -> Float,
crossinline groupOp: (List) -> G,
rangeStart: Float? = null
): BinModel = toList().binByFloat(binSize, valueSelector, groupOp, rangeStart)
inline fun List.binByFloat(binSize: Float,
crossinline valueSelector: (T) -> Float,
rangeStart: Float? = null
): BinModel, Float> = binByFloat(binSize, valueSelector, { it }, rangeStart)
inline fun List.binByFloat(binSize: Float,
crossinline valueSelector: (T) -> Float,
crossinline groupOp: (List) -> G,
rangeStart: Float? = null
): BinModel {
val groupedByC = asSequence().groupBy { BigDecimal.valueOf(valueSelector(it).toDouble()) }
val minC = rangeStart?.toDouble()?.let(BigDecimal::valueOf) ?:groupedByC.keys.min()!!
val maxC = groupedByC.keys.max()!!
val bins = mutableListOf>().apply {
var currentRangeStart = minC
var currentRangeEnd = minC
val isFirst = AtomicBoolean(true)
val binSizeBigDecimal = BigDecimal.valueOf(binSize.toDouble())
while (currentRangeEnd < maxC) {
currentRangeEnd = currentRangeStart + binSizeBigDecimal
add(currentRangeStart.toFloat() until currentRangeEnd.toFloat())
currentRangeStart = currentRangeEnd
}
}
return bins.asSequence()
.map { it to mutableListOf() }
.map { binWithList ->
groupedByC.entries.asSequence()
.filter { it.key.toFloat() in binWithList.first }
.forEach { binWithList.second.addAll(it.value) }
binWithList
}.map { Bin(it.first, groupOp(it.second)) }
.toList()
.let(::BinModel)
}