Last active
April 1, 2017 21:00
-
-
Save nanu146/df39c69d1d0cb1b71429b2cd47e2a189 to your computer and use it in GitHub Desktop.
Heatmap using d3.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: gpl-3.0 | |
height: 900 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
x | y | value | |
---|---|---|---|
France | Apricot | 2.3129545439964723 | |
France | Avocado | 3.1610140317890965 | |
France | Lemon | 0.9075695440623942 | |
France | Date | 1.1296454803177811 | |
France | Strawberry | ||
France | Mandarin | 2.6193568568512493 | |
France | Chestnut | 0.08748279136251946 | |
France | Nuts | 2.943858242639327 | |
France | Olive | 1.3356914547843943 | |
France | Mirabelle | 0.31390905400247027 | |
France | Orange | 0.5709024568447734 | |
France | Fig | 0.8689875977541086 | |
France | Raisin | ||
France | Pear | ||
France | Potato | ||
France | Khaki | ||
France | Kiwi | 6.026783469350332 | |
France | Pumpkin | 0.5472217416389179 | |
France | Mango | ||
France | Cherry | 1.9472375734686518 | |
Italy | Apricot | 2.250335336990016 | |
Italy | Avocado | 1.4472931892677967 | |
Italy | Lemon | 1.7163168911863054 | |
Italy | Date | 0.6222770814456479 | |
Italy | Strawberry | ||
Italy | Mandarin | 1.9378611429750559 | |
Italy | Goyave | ||
Italy | Chestnut | 0.35446193006796944 | |
Italy | Nuts | 0.37199215156032084 | |
Italy | Olive | 1.05979039016384 | |
Italy | Orange | 1.9087621718437413 | |
Italy | Fig | 4.632439392448328 | |
Italy | Raisin | ||
Italy | Pear | ||
Italy | Potato | ||
Italy | Khaki | ||
Italy | Banana | ||
Italy | Blackcurrant | ||
Italy | Kiwi | 1.673923311217576 | |
Italy | Pumpkin | 0.8029920360319587 | |
Italy | Cherry | 1.9453249240219272 | |
Germany | Apricot | 0.24786564820472912 | |
Germany | Avocado | 1.13545847239482 | |
Germany | Lemon | 0.6388067539810734 | |
Germany | Date | 1.626323182055196 | |
Germany | Strawberry | ||
Germany | Mandarin | 0.4239980281990543 | |
Germany | Chestnut | 1.4341389749588975 | |
Germany | Nuts | 0.7392983316104583 | |
Germany | Olive | 1.6630071601899028 | |
Germany | Mirabelle | 4.759329801939115 | |
Germany | Orange | 3.718673834416696 | |
Germany | Fig | 2.458679694479642 | |
Germany | Raisin | ||
Germany | Pear | ||
Germany | Potato | ||
Germany | Prune | ||
Germany | Khaki | ||
Germany | Banana | ||
Germany | Ananas | ||
Germany | Kiwi | 1.3234705953824204 | |
Germany | Pumpkin | 0.0770059996293927 | |
Germany | Cherry | 1.7111604775075815 | |
United Kingdom | Apricot | 0.17924671480874477 | |
United Kingdom | Avocado | 0.022885648078082133 | |
United Kingdom | Lemon | 1.7152082470441878 | |
United Kingdom | Date | 1.752070575653172 | |
United Kingdom | Mandarin | 3.4281163770331387 | |
United Kingdom | Goyave | ||
United Kingdom | Chestnut | 0.19739811992921974 | |
United Kingdom | Nuts | 1.0070422960846344 | |
United Kingdom | Olive | 2.228287010523628 | |
United Kingdom | Orange | 0.9304979227921532 | |
United Kingdom | Fig | 0.5953329645659061 | |
United Kingdom | Cerise | ||
United Kingdom | Raisin | ||
United Kingdom | Potato | ||
United Kingdom | Prune | ||
United Kingdom | Khaki | ||
United Kingdom | Ananas | ||
United Kingdom | Kiwi | 3.9494022464067755 | |
United Kingdom | Pumpkin | 2.2009939178127476 | |
United Kingdom | Mango | ||
United Kingdom | Cherry | 0.20063602688693316 | |
Spain | Apricot | 0.9989751140631283 | |
Spain | Avocado | 1.3798561037495776 | |
Spain | Lemon | 4.621063369745371 | |
Spain | Date | 2.715496746864414 | |
Spain | Strawberry | ||
Spain | Mandarin | 4.655686656785712 | |
Spain | Chestnut | 2.0830024325290624 | |
Spain | Nuts | 3.8907348191368603 | |
Spain | Olive | 0.4593907900702838 | |
Spain | Mirabelle | 0.8657861030686699 | |
Spain | Orange | 3.431725506748977 | |
Spain | Fig | 6.387945884767135 | |
Spain | Raisin | ||
Spain | Pear | ||
Spain | Potato | ||
Spain | Khaki | ||
Spain | Kiwi | 1.1520183768223036 | |
Spain | Pumpkin | 1.9614971869756583 | |
Spain | Cherry | 1.7489279548209826 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: black; | |
shape-rendering: crispEdges; | |
} | |
.axis text { | |
font-family: sans-serif; | |
font-size: 11px; | |
} | |
.heatmap{ | |
top:110px; | |
position: relative; | |
} | |
</style> | |
<div class="heatmap"></div> | |
<script src="//d3js.org/d3.v4.min.js"></script> | |
<script> | |
/* | |
negative color scales in increasing magnitude | |
#EF9FAE, #C76475, #781426 | |
positive color scales in increasing magnitude | |
#ABDB92, #77B75B, #2E6E12 | |
*/ | |
/* supporting functions */ | |
// Standard deviation | |
function RMS(arr){ | |
return Math.pow(arr.reduce(function(acc,pres){ | |
return acc+ Math.pow(pres,2); | |
})/arr.length,.5) | |
} | |
// mean | |
function mean(arr){ | |
return arr.reduce(function(acc,prev){ | |
return acc+prev; | |
})/arr.length; | |
} | |
var lPatchWidth=200; | |
var itemSize = 22, | |
cellSize = itemSize - 3, | |
margin = {top: 50, right: 20, bottom: 120, left: 110}; | |
var data; | |
var width = 750 - margin.right - margin.left, | |
height = 300 - margin.top - margin.bottom; | |
var colorScale; | |
colorHold=["#781426","#C76475","#EF9FAE","#ABDB92","#77B75B","#2E6E12"] | |
colorLText=["< -66%","-66% to -33%","-33% to 0%","0% to 33%","33% to 66%","> 66%"] | |
function bandClassifier(val,multiplier) | |
{ | |
if(val>=0) | |
{ | |
return (Math.floor((val*multiplier)/(.33*multiplier))+1)>3?3:Math.floor((val*multiplier)/(.33*multiplier))+1 | |
} | |
else{ | |
return (Math.floor((val*multiplier)/(.33*multiplier)))<-3?-3:Math.floor((val*multiplier)/(.33*multiplier)) | |
} | |
} | |
window.onload=function(){ | |
d3.csv('data.csv', function ( response ) { | |
data = response.map(function( item ) { | |
var newItem = {}; | |
newItem.country = item.x; | |
newItem.product = item.y; | |
newItem.value = +item.value; | |
return newItem; | |
}) | |
invertcolors=0; | |
// Inverting color scale | |
if(invertcolors){ | |
colorHold.reverse(); | |
} | |
var x_elements = d3.set(data.map(function( item ) { return item.product; } )).values(), | |
y_elements = d3.set(data.map(function( item ) { return item.country; } )).values(); | |
var xScale = d3.scaleBand() | |
.domain(x_elements) | |
.range([0, x_elements.length * itemSize]) | |
.paddingInner(20).paddingOuter(cellSize/2) | |
var xAxis = d3.axisBottom() | |
.scale(xScale) | |
.tickFormat(function (d) { | |
return d; | |
}); | |
var yScale = d3.scaleBand() | |
.domain(y_elements) | |
.range([0, y_elements.length * itemSize]) | |
.paddingInner(.2).paddingOuter(.2); | |
var yAxis = d3.axisLeft() | |
.scale(yScale) | |
.tickFormat(function (d) { | |
return d; | |
}); | |
// Finding the mean of the data | |
var mean=window.mean(data.map(function(d){return +d.value})); | |
//setting percentage change for value w.r.t average | |
data.forEach(function(d){ | |
d.perChange=(d.value-mean)/mean | |
}) | |
colorScale = d3.scaleOrdinal() | |
.domain([-3,-2,-1,1,2,3]) | |
.range(colorHold); | |
var rootsvg = d3.select('.heatmap') | |
.append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
var svg=rootsvg.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
// tooltip | |
tooltip=d3.select("body").append("div").style("width","80px").style("height","40px").style("background","#C3B3E5") | |
.style("opacity","1").style("position","absolute").style("visibility","hidden").style("box-shadow","0px 0px 6px #7861A5").style("padding","10px"); | |
toolval=tooltip.append("div"); | |
var cells = svg.selectAll('rect') | |
.data(data) | |
.enter().append('g').append('rect') | |
.attr('class', 'cell') | |
.attr('width', cellSize) | |
.attr('height', cellSize) | |
.attr('y', function(d) { return yScale(d.country); }) | |
.attr('x', function(d) { return xScale(d.product)-cellSize/2; }) | |
.attr('fill', function(d) { return colorScale(window.bandClassifier(d.perChange,100));}) | |
.attr("rx",3) | |
.attr("ry",3) | |
.on("mouseover",function(d){ | |
console.log(d); | |
//d3.select(this).attr("fill","#655091"); | |
d3.select(this).style("stroke","orange").style("stroke-width","3px") | |
d3.select(".trianglepointer").transition().delay(100).attr("transform","translate("+(-((lPatchWidth/colorScale.range().length)/2+(colorScale.domain().indexOf(bandClassifier(d.perChange,100))*(lPatchWidth/colorScale.range().length) )))+",0)"); | |
d3.select(".LegText").select("text").text(colorLText[colorScale.domain().indexOf(bandClassifier(d.perChange,100))]) | |
}) | |
.on("mouseout",function(){ | |
//d3.select(this).attr('fill', function(d) { return colorScale(window.bandClassifier(d.perChange,100));}); | |
d3.select(this).style("stroke","none"); | |
tooltip.style("visibility","hidden"); | |
}) | |
.on("mousemove",function(d){ | |
tooltip.style("visibility","visible") | |
.style("top",(d3.event.pageY-30)+"px").style("left",(d3.event.pageX+20)+"px"); | |
console.log(d3.mouse(this)[0]) | |
tooltip.select("div").html("<strong>"+d.product+"</strong><br/> "+(+d.value).toFixed(2)) | |
}) | |
svg.append("g") | |
.attr("class", "y axis") | |
.call(yAxis) | |
.selectAll('text') | |
.attr('font-weight', 'normal'); | |
svg.append("g") | |
.attr("class", "x axis") | |
.attr("transform","translate(0,"+(y_elements.length * itemSize +cellSize/2)+")") | |
.call(xAxis) | |
.selectAll('text') | |
.attr('font-weight', 'normal') | |
.style("text-anchor", "end") | |
.attr("dx", "-.8em") | |
.attr("dy", "-.5em") | |
.attr("transform", function (d) { | |
return "rotate(-65)"; | |
}); | |
// Legends section | |
legends=svg.append("g").attr("class","legends") | |
.attr("transform","translate("+((width+margin.right)/2-lPatchWidth/2 -margin.left/2)+","+(height+margin.bottom-35-20)+")"); | |
// Legend traingle pointer generator | |
var symbolGenerator = d3.symbol() | |
.type(d3.symbolTriangle) | |
.size(64); | |
legends.append("g").attr("transform","rotate(180)").append("g").attr("class","trianglepointer") | |
.attr("transform","translate("+(-lPatchWidth/colorScale.range().length)/2+")") | |
.append("path").attr("d",symbolGenerator()); | |
//Legend Rectangels | |
legends.append("g").attr("class","LegRect") | |
.attr("transform","translate(0,"+15+")") | |
.selectAll("rect").data(colorScale.range()).enter() | |
.append("rect").attr("width",lPatchWidth/colorScale.range().length+"px").attr("height","10px").attr("fill",function(d){ return d}) | |
.attr("x",function(d,i){ return i*(lPatchWidth/colorScale.range().length) }) | |
// legend text | |
legends.append("g").attr("class","LegText") | |
.attr("transform","translate(0,45)") | |
.append("text") | |
.attr("x",lPatchWidth/2) | |
.attr('font-weight', 'normal') | |
.style("text-anchor", "middle") | |
.text(colorLText[0]) | |
// Heading | |
rootsvg.append("g") | |
.attr("transform","translate(0,30)") | |
.append("text") | |
.attr("x",(width+margin.right+margin.left)/2) | |
.attr('font-weight', 'bold') | |
.attr('font-size', '22px') | |
.attr('font-family', 'Segoe UI bold') | |
.style("text-anchor", "middle") | |
.text("Sales Heatmap") | |
}); | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment