import { median } from 'd3-array' ; import * as jStat from 'jstat' ; import type { IConfidenceInterval } from './stats' ; import { toNearestHundreth } from './utils' ; private function _defaultModifier ( x , y ) { return x - y ; } param listOne param listTwo param func export function cartesianProduct ( listOne , listTwo , func = _defaultModifier ) { let results = [ ] ; listOne . forEach ( ( x ) => { listTwo . forEach ( ( y ) => { results . push ( func ( x , y ) ) ; } ) ; } ) ; results = results . sort ( ( a , b ) => a - b ) ; return results ; } param distributionOne param distributionTwo param interval export function confidenceInterval ( a , b , confidence ) { const aLength = a . length ; const bLength = b . length ; const maxU = aLength * bLength ; const meanU = maxU / 2 ; const deltas = a . map ( ( a ) => b . map ( ( b ) => a - b ) ) . flat ( ) . sort ( ( a , b ) => a - b ) ; const U = deltas . reduce ( ( accum , value ) => accum + ( value < 0 ? 1 : value == 0 ? 0.5 : 0 ) , 0 ) ; const lowerTail = U <= meanU ; const standardDeviationU = Math . sqrt ( ( maxU * ( aLength + bLength + 1 ) ) / 12 ) ; const continuityCorrection = lowerTail ? 0.5 : - 0.5 ; const zScore = ( U - meanU + continuityCorrection ) / standardDeviationU ; const pValue = jStat . normal . cdf ( - Math . abs ( zScore ) , 0 , 1 ) * 2 ; const alpha = 1 - confidence ; const lowerU = Math . round ( jStat . normal . inv ( alpha / 2 , meanU + 0.5 , standardDeviationU ) ) ; const upperU = Math . round ( jStat . normal . inv ( 1 - alpha / 2 , meanU + 0.5 , standardDeviationU ) ) ; const aMedian = median ( a ) as number ; const medianDeltas = median ( deltas ) as number ; return { min : deltas [ lowerU ] , median : medianDeltas ?? 0 , max : deltas [ upperU ] , zScore : + zScore . toPrecision ( 4 ) , pValue : + pValue . toPrecision ( 4 ) , U , asPercent : { percentMin : toNearestHundreth ( ( deltas [ lowerU ] / aMedian ) * 100 ) , percentMedian : toNearestHundreth ( ( medianDeltas / aMedian ) * 100 ) ?? 0 , percentMax : toNearestHundreth ( ( deltas [ upperU ] / aMedian ) * 100 ) } } ; }