The Kruskal-Wallis test is a non-parametric one-way analysis of variance by ranks (named after William Kruskal and W. Allen Wallis) for testing equality of population medians among groups (see [http://en.wikipedia.org/wiki/Kruskal–Wallis_one-way_analysis_of_variance] for more information). This test is missing from the [tcllib] [math] package (here: [::math::statistics]), so here is an implementation. It can easily be taken apart to use the ranking of groups of values as a separate command, since this is needed separately fro the test in other occasions. My implemention takes a list of groups where each group is a list of values. It returns a list with the H value (the test result) and the p value (i.e. the probability of a H value this large or larger). The latter is computed using ::math::statistics::cdf-chisquare, so the tcllib math::statistics package is needed. Here is code: ====== package require Tcl 8.4 package require math::statistics proc kw-h {args} { set index 0 set rankList [list] set setCount [llength $args] # read lists of values: foreach item $args { set values($index) [lindex $args $index] # prepare ranking with rank=0: foreach value $values($index) {lappend rankList [list $index $value 0]} incr index 1 } # sort the values: set rankList [lsort -real -index 1 $rankList] # assign the ranks (disregarding ties): set length [llength $rankList] for {set i 0} {$i < $length} {incr i} { lset rankList $i 2 [expr {$i + 1}] } # value of the previous list element: set prevValue {} # list of indices of list elements having the same value (ties): set equalIndex [list] # test for ties and re-assign mean ranks for tied values: for {set i 0} {$i < $length} {incr i} { set value [lindex $rankList $i 1] if {($value != $prevValue) && ($i > 0) && ([llength $equalIndex] > 0)} { # we are still missing the first tied value: set j [lindex $equalIndex 0] incr j -1 set equalIndex [linsert $equalIndex 0 $j] # re-assign rank as mean rank of tied values: set firstRank [lindex $rankList [lindex $equalIndex 0] 2] set lastRank [lindex $rankList [lindex $equalIndex end] 2] set newRank [expr {($firstRank+$lastRank)/2.0}] foreach j $equalIndex {lset rankList $j 2 $newRank} # clear list of equal elements: set equalIndex [list] } elseif {$value == $prevValue} { # remember index of equal value element: lappend equalIndex $i } set prevValue $value } # re-establish original sets of values, but using the ranks: foreach item $rankList { lappend rankValues([lindex $item 0]) [lindex $item 2] } # now compute H: set H 0 for {set i 0} {$i < $setCount} {incr i} { set total [expr [join $rankValues($i) +]] set count [llength $rankValues($i)] set H [expr {$H + pow($total,2)/double($count)}] } set H [expr {$H*(12.0/($length*($length + 1))) - (3*($length + 1))}] incr setCount -1 set p [expr {1 - [::math::statistics::cdf-chisquare $setCount $H]}] return [list $H $p] } ====== Now, an example (the same as on this page: [http://faculty.vassar.edu/lowry/ch14a.html]) ====== % puts [kw-h {6.4 6.8 7.2 8.3 8.4 9.1 9.4 9.7} {2.5 3.7 4.9 5.4 5.9 8.1 8.2} {1.3 4.1 4.9 5.2 5.5 8.2}] 9.83627087199 0.00731275323967 ====== ---- See also: * [Chi-squared distribution] * [Statistical distributions] <>Mathematics| Statistics