global ready set ready 0 proc histogram {slist wid ht} { ;# render a histogram global ready array set scores $slist set nms [lsort -integer [array names scores]] catch {destroy .h} {} catch {destroy .b} {} canvas .h -width $wid -height $ht -bg beige pack .h set nbars [array size scores] ;#how many histogram bars set nax [expr $nbars/10] ;# axis spacing set hwid [expr $wid/ $nbars] set i 0 set hmax -9999999 ;# largest y value set hmin 9999999 ;# smallest y value while {$i<$nbars} { set f $scores([lindex $nms $i]) set hmax [ expr {$f>$hmax} ? $f : $hmax] set hmin [ expr {$f<$hmin} ? $f : $hmin] incr i } if {$hmax>$hmin} { set i 0 set nay 100 while {$nay<$hmax} { set yp [expr $ht-0.75*$nay-20] .h create line 0 $yp $wid $yp -fill red incr nay 100 } set nax 10 while {$i<$nbars} { set x [expr $hwid*$i] set rhs [expr $x+$hwid/2] set f [expr $ht-20-.75*$ht*$scores([lindex $nms $i])/$hmax] .h create rectangle $x [expr $ht-20] $rhs $f -fill gray if {[expr $i>=$nax]} { .h create line $x [expr $ht-20] $x 0 -fill red incr nax 10 } incr i incr x $hwid } update # button .b -text "Next" -command "incr ready" ;# when ready is changed, proceeds with commands # pack .b } }
Call using
histogram {1 2 2 3 3 5 4 7 5 6} 500 400The list is actually an array :: category 1 occurred twice; category 2 three times, category 3 5 times, category 4 7 times & 5 occurred 6 times. The category names must be integers. For a way of looking at the rand function:
for {set i 0} {$i<50} {incr i} {lappend scores $i [expr rand()]} histogram $scores 500 200will show a histogram of the value returned by rand for 50 trials (nb not the frequency).For rand frequency of the first digit returned by rand() use:
for {set i 0} {$i<10} {incr i} {set rnd($i) 0} for {set i 0} {$i<50} {incr i} { incr rnd([expr int(9.9999*rand())])} histogram [array get rnd] 300 200Repeatedly paste this code into wish console to see the variation in frequency of each integer value.Other graphics routinesSee also