forked from nanu146's block: Heatmap using d3.js
Created
March 6, 2019 12:58
-
-
Save GerardoFurtado/a5153b4a293d72325c1aaee0b9aaac0c 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="https://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) | |
.tickSizeOuter(0) | |
.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