Prompted by a tweet by @peteaven pointing to an article from Flowing Data on How to make a Heat map using R for generating heat maps, I thought I'd give it a go in XQuery.
Here is my first attempt using XQuery and generating HTML.This assumes that the csv data is formated with the first column a row identifier and the rest of the columns containing data to be heat mapped.
Parameters supply the csv URI, the palette (here chosen with the help of the excellent colorBrewer site) and the heatmap title.
The CSV is first parsed to an XML structure : a table of row containing cells witha header.
The data ranges are computed for each data column:
declare function local:ranges($rows, $ncols, $n) { for $i in (2 to $ncols) let $min := min($rows/*[$i]) let $max := max($rows/*[$i]) let $range := $max - $min let $interval := $range div $n return <range min = "{$min}" interval="{$interval}" /> };
A function generates each cell using the range for the column to map the value linearly into the palette:
declare function local:spot($value, $title, $palette, $range) { let $n := max ((floor(($value - $range/@min) div $range/@interval), 1)) return <td title="{$title}"> <span style= 'background-color:{ $palette [$n]} ' >        </span> </td> };
To generate the table body:
for $row in $table/row return <tr> <th>{string($row/*[1])}</th> {for $col at $i in (2 to $ncols) let $value := $row/*[$col] let $title := concat($table/header/*[$col] ," = ",$value) return local:spot($value, $title ,$palette,$ranges[$i ] ) } </tr>
The rest of the script does housekeeping and table generation. A common library function using the eist httpclient function handles the csv conversion.