All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nield.kotlinstatistics.FloatStatistics.kt Maven / Gradle / Ivy

There is a newer version: 1.2.1
Show newest version
import org.apache.commons.math3.stat.StatUtils
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics
import org.nield.kotlinstatistics.*
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()







// Bin Operators

inline fun  Sequence.binByFloat(binSize: Float,
                                      gapSize: Float,
                                      crossinline valueSelector: (T) -> Float,
                                      rangeStart: Float? = null
): BinModel, Float> = toList().binByFloat(binSize, gapSize, valueSelector, { it }, rangeStart)

inline fun  Sequence.binByFloat(binSize: Float,
                                         gapSize: Float,
                                         crossinline valueSelector: (T) -> Float,
                                         crossinline groupOp: (List) -> G,
                                         rangeStart: Float? = null
): BinModel = toList().binByFloat(binSize, gapSize, valueSelector, groupOp, rangeStart)


inline fun  Iterable.binByFloat(binSize: Float,
                                  gapSize: Float,
                                  crossinline valueSelector: (T) -> Float,
                                  rangeStart: Float? = null
): BinModel, Float> = toList().binByFloat(binSize, gapSize, valueSelector, { it }, rangeStart)

inline fun  Iterable.binByFloat(binSize: Float,
                                     gapSize: Float,
                                     crossinline valueSelector: (T) -> Float,
                                     crossinline groupOp: (List) -> G,
                                     rangeStart: Float? = null
): BinModel = toList().binByFloat(binSize, gapSize, valueSelector, groupOp, rangeStart)


inline fun  List.binByFloat(binSize: Float,
                                   gapSize: Float,
                                   crossinline valueSelector: (T) -> Float,
                                   rangeStart: Float? = null
): BinModel, Float> = binByFloat(binSize, gapSize, valueSelector, { it }, rangeStart)

inline fun  List.binByFloat(binSize: Float,
                                     gapSize: 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())
        val gapSizeBigDecimal = BigDecimal.valueOf(gapSize.toDouble())
        while  (currentRangeEnd < maxC) {
            currentRangeEnd = currentRangeStart + binSizeBigDecimal - if (isFirst.getAndSet(false)) BigDecimal.ZERO else gapSizeBigDecimal
            add(currentRangeStart.toFloat()..currentRangeEnd.toFloat())
            currentRangeStart = currentRangeEnd + gapSizeBigDecimal
        }
    }

    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)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy