export const wilcoxonRankSumTable = [ 0 , 0 , 0 , 10 , 17 , 26 , 36 , 49 , 62 , 78 , 96 , 115 , 136 , 160 , 184 , 211 , 240 , 270 , 303 , 337 , 373 , 411 , 451 , 491 , 536 ] ; interface ISample { val : number ; rank : number ; pool : number [ ] ; samples : number [ ] ; } export function getMergedSortedSamples ( control , experiment ) { return [ ... control , ... experiment ] . sort ( ( a , b ) => a - b ) ; } export function getSamples ( a , pool ) { a . sort ( ( a , b ) => a - b ) ; return a . map ( ( val ) => { return { val , rank : 0 , pool , samples : a } ; } ) ; } export function rankSamples ( samples ) { const sa = samples ; sa . forEach ( ( sample ) => { sample . pool . forEach ( ( p , i ) => { if ( sample . val === p ) { sample . rank = i + 1 ; } } ) ; } ) ; function countDuplicates ( obj , num ) { obj [ num ] = ( ++ obj [ num ] || 1 ) ; return obj ; } sa . forEach ( ( sample ) => { const acc = sample . pool . reduce ( countDuplicates , { } as any ) ; if ( acc [ sample . val ] > 1 ) { sample . rank = ( sample . rank - 0.5 ) ; } } ) ; return sa ; } export function getRankSum ( rankedSamples ) { return rankedSamples . reduce ( ( currentSum , sample ) => { return currentSum + sample . rank ; } , 0 ) ; } export function getSampleUStat ( rankSum , N ) { return rankSum - ( N * ( N + 1 ) ) / 2 ; } param control param experiment export function getWilcoxonRankSumTest ( control , experiment ) { const N = control . length ; const samplePool = getMergedSortedSamples ( control , experiment ) ; const controlSamples = getSamples ( control , samplePool ) ; const experimentSamples = getSamples ( experiment , samplePool ) ; const rankedControlSamples = rankSamples ( controlSamples ) ; const rankedExperimentSamples = rankSamples ( experimentSamples ) ; const controlRankSum = getRankSum ( rankedControlSamples ) ; const experimentRankSum = getRankSum ( rankedExperimentSamples ) ; const uStatControl = getSampleUStat ( controlRankSum , N ) ; const uStatExperiment = getSampleUStat ( experimentRankSum , N ) ; const uStat = Math . min ( uStatControl , uStatExperiment ) ; if ( N > 25 ) { throw new Error ( `Sample sizes greater than 25 are not supported. Your sample size is ${ N }` ) ; } const uCrit = wilcoxonRankSumTable [ N ] ; return uStat < uCrit ; }