Plotting a score card
Arjen Markus (29 may 2022) I was faced with the problem of presenting the scores of an evaluation procedure. The subject: judge the suitability of datasets. The datasets are judged on a variety of criteria, but the challenge was that there were two sets of criteria and we need to combine them in such a way that the scores for each set are visible and the overall score. To keep it short:
One way of dealing with this problem is via a "spider diagram" or a "radial plot", as they are called in Plotchart. But then it is difficult to see the combination - the two lines representing the score for each set would cross each other most probably and what would that mean?
A chart type in use in reports on climate change gave me the inspiration to come up with a slightly different approach:
Here is the resulting plot, well, it is an example and to keep it general I have left out the particular texts.
The code given below draws this plot. The input consists of:
Nothing mysterious: it is an experiment. And the data are completely arbitrary.
The first file (maxscore.inp):
Category 1, 100, 4, 0 Category 2, 30, 6, 2 Category 3, 50, 2, 4 Category 4, 30, 2, 8 Category 5, 70, 14, 4 Category 6, 0, 0, 4 Category 7, 70, 6, 4
The second file (actual scores, score.inp):
Category 1, 3, 0 Category 2, 3, 2 Category 3, 2, 2 Category 4, 2, 6 Category 5, 10, 4 Category 6, 0, 1 Category 7, 6, 4
And the code, a trifle ad hoc, but it serves to illustrate the graphical representation:
# plotscore.tcl -- # Prototype for scoring plots: # - The circle is filled with segments for the seven categories # - Each segment is divided in two parts, one for each set of criteria # - The maximum area assigned to the two aspects depends on the weight for the first set of criteria # - The actual area depends on the actual score # # # Set up the canvas with the central circle # pack [canvas .c -width 1000 -height 800] set xleft 200 set ytop 200 set xright 700 set ybottom 700 .c create oval $xleft $ytop $xright $ybottom -fill #ff5555 # # Read the category information # set infile [open "maxscore.inp"] set categories {} while { [gets $infile line] >= 0 } { lappend categories [split $line ,] } close $infile # # Read the actual scores # set infile [open "score.inp"] set scores {} while { [gets $infile line] >= 0 } { lappend scores [split $line ,] } close $infile # # Draw the sectors # set angle 90.0 set dangle [expr {360.0 / [llength $categories]}] set xcentre [expr {($xleft + $xright) / 2.0}] set ycentre [expr {($ytop + $ybottom) / 2.0}] set radius [expr {($xright - $xleft) / 2.0}] set torad [expr {acos(-1.0)/180.0}] foreach category $categories score $scores { set weight [expr {[lindex $category 1] / 100.0}] set score1 [expr {[lindex $score 1] / double([lindex $category 2] + 0.000001)}] set score2 [expr {[lindex $score 2] / double([lindex $category 3] + 0.000001)}] set radius1 [expr {$radius * $weight * $score1}] set radius2 [expr {$radius1 + $radius * (1.0 - $weight) * $score2}] set xscoreL [expr {$xcentre - $radius2}] set xscoreR [expr {$xcentre + $radius2}] set yscoreT [expr {$ycentre - $radius2}] set yscoreB [expr {$ycentre + $radius2}] .c create arc $xscoreL $yscoreT $xscoreR $yscoreB -fill lime -start $angle -extent $dangle set xscoreL [expr {$xcentre - $radius1}] set xscoreR [expr {$xcentre + $radius1}] set yscoreT [expr {$ycentre - $radius1}] set yscoreB [expr {$ycentre + $radius1}] .c create arc $xscoreL $yscoreT $xscoreR $yscoreB -fill green -start $angle -extent $dangle set at [expr {$angle + $dangle/2.0}] set xt [expr {$xcentre + 1.1 * $radius * cos($at*$torad)}] set yt [expr {$ycentre - 1.1 * $radius * sin($at*$torad)}] if { $at > 90.0 && $at < 260.0} { set anchor e } elseif { $at > 260.0 && $at < 280.0 } { set anchor n } else { set anchor w } .c create text $xt $yt -text [lindex $category 0] -font "Helvetica 14 bold" -anchor $anchor set angle [expr {$angle + $dangle}] } # # Circles for reference: 50% and 70% of the area (!) # Skipped # if {0} { foreach percentage {50 70} { set radiusP [expr {$radius * sqrt($percentage / 100.0)}] set xscoreL [expr {$xcentre - $radiusP}] set xscoreR [expr {$xcentre + $radiusP}] set yscoreT [expr {$ycentre - $radiusP}] set yscoreB [expr {$ycentre + $radiusP}] .c create oval $xscoreL $yscoreT $xscoreR $yscoreB -width 2 } } # # The legend # .c create rectangle [expr {$xcentre - 0.7*$radius}] 35 [expr {$xcentre - 0.7*$radius + 30}] 65 -fill green .c create rectangle [expr {$xcentre - 0.7*$radius}] 75 [expr {$xcentre - 0.7*$radius + 30}] 105 -fill lime .c create rectangle [expr {$xcentre - 0.7*$radius}] 115 [expr {$xcentre - 0.7*$radius + 30}] 145 -fill #ff5555 .c create text [expr {$xcentre - 0.7*$radius + 50}] 50 -text "Criteria set 1" -font "Helvetica 14 bold" -anchor w .c create text [expr {$xcentre - 0.7*$radius + 50}] 90 -text "Criteria set 2" -font "Helvetica 14 bold" -anchor w .c create text [expr {$xcentre - 0.7*$radius + 50}] 130 -text "Shortcomings" -font "Helvetica 14 bold" -anchor w