D3.js heatmap with color - javascript

Hi I am trying to add in a color scale for my heat map. I Specifically want to use d3.schemeRdYlBu this color scheme but I am having a hard time implementing it. At the moment it just does black. I also have a hover feature with this so I would like that to still work but i am more concerned with just getting the color to work. Obviously having the lower numbers be blue and the higher numbers be red to indicate temp
<!DOCTYPE html>
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<!-- Load color palettes -->
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<script>
// set the dimensions and margins of the graph
var margin = {top: 80, right: 25, bottom: 30, left: 40},
width = 1000 - margin.left - margin.right,
height = 1000 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
//Read the data
d3.csv("https://raw.githubusercontent.com/Nataliemcg18/Data/master/NASA_Surface_Temperature.csv", function(data) {
// Labels of row and columns -> unique identifier of the column called 'group' and 'variable'
var myGroups = d3.map(data, function(d){return d.group;}).keys()
var myVars = d3.map(data, function(d){return d.variable;}).keys()
// Build X scales and axis:
var x = d3.scaleBand()
.range([ 0, width ])
.domain(myGroups)
.padding(0.05);
svg.append("g")
.style("font-size", 15)
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickSize(0))
.select(".domain").remove()
// Build Y scales and axis:
var y = d3.scaleBand()
.range([ height, 0 ])
.domain(myVars)
.padding(0.05);
svg.append("g")
.style("font-size", 15)
.call(d3.axisLeft(y).tickSize(0))
.select(".domain").remove()
// Build color scale
var myColor = (d3.schemeRdYlBu[2])
// create a tooltip
var tooltip = d3.select("#my_dataviz")
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px")
// Three function that change the tooltip when user hover / move / leave a cell
var mouseover = function(d) {
tooltip
.style("opacity", 1)
d3.select(this)
.style("stroke", "green")
.style("opacity", 1)
}
var mousemove = function(d) {
tooltip
.html("The exact value of this cell is: " + d.value, )
.style("left", (d3.mouse(this)[0]+70) + "px")
.style("top", (d3.mouse(this)[1]) + "px")
}
var mouseleave = function(d) {
tooltip
.style("opacity", 0)
d3.select(this)
.style("stroke", "none")
.style("opacity", 0.8)
}
// add the squares
svg.selectAll()
.data(data, function(d) {return d.group+':'+d.variable;})
.enter()
.append("rect")
.attr("x", function(d) { return x(d.group) })
.attr("y", function(d) { return y(d.variable) })
.attr("rx", 4)
.attr("ry", 4)
.attr("width", x.bandwidth() )
.attr("height", y.bandwidth() )
.style("fill", function(d) { return myColor(d.value)} )
.style("stroke-width", 4)
.style("stroke", "none")
.style("opacity", 0.8)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave)
})
// Add title to graph
svg.append("text")
.attr("x", 0)
.attr("y", -50)
.attr("text-anchor", "left")
.style("font-size", "22px")
.text("A d3.js heatmap");
// Add subtitle to graph
svg.append("text")
.attr("x", 0)
.attr("y", -20)
.attr("text-anchor", "left")
.style("font-size", "14px")
.style("fill", "grey")
.style("max-width", 400)
.text("A short description of the take-away message of this chart.");
</script>

You can use arrow function instead of the regular function to use your own binding of this for accessing myColor variable.
<!DOCTYPE html>
<meta charset="utf-8" />
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<!-- Load color palettes -->
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<script>
// set the dimensions and margins of the graph
var margin = { top: 80, right: 25, bottom: 30, left: 40 },
width = 1000 - margin.left - margin.right,
height = 1000 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3
.select("#my_dataviz")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//Read the data
d3.csv(
"https://raw.githubusercontent.com/Nataliemcg18/Data/master/NASA_Surface_Temperature.csv",
function (data) {
// Labels of row and columns -> unique identifier of the column called 'group' and 'variable'
var myGroups = d3
.map(data, function (d) {
return d.group;
})
.keys();
var myVars = d3
.map(data, function (d) {
return d.variable;
})
.keys();
// Build X scales and axis:
var x = d3.scaleBand().range([0, width]).domain(myGroups).padding(0.05);
svg
.append("g")
.style("font-size", 15)
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickSize(0))
.select(".domain")
.remove();
// Build Y scales and axis:
var y = d3.scaleBand().range([height, 0]).domain(myVars).padding(0.05);
svg
.append("g")
.style("font-size", 15)
.call(d3.axisLeft(y).tickSize(0))
.select(".domain")
.remove();
// Build color scale
var myColor = d3.schemeRdYlBu[3][2];
// create a tooltip
var tooltip = d3
.select("#my_dataviz")
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px");
// Three function that change the tooltip when user hover / move / leave a cell
var mouseover = function (d) {
tooltip.style("opacity", 1);
d3.select(this).style("stroke", "green").style("opacity", 1);
};
var mousemove = function (d) {
tooltip
.html("The exact value of this cell is: " + d.value)
.style("left", d3.mouse(this)[0] + 70 + "px")
.style("top", d3.mouse(this)[1] + "px");
};
var mouseleave = function (d) {
tooltip.style("opacity", 0);
d3.select(this).style("stroke", "none").style("opacity", 0.8);
};
// add the squares
svg
.selectAll()
.data(data, function (d) {
return d.group + ":" + d.variable;
})
.enter()
.append("rect")
.attr("x", function (d) {
return x(d.group);
})
.attr("y", function (d) {
return y(d.variable);
})
.attr("rx", 4)
.attr("ry", 4)
.attr("width", x.bandwidth())
.attr("height", y.bandwidth())
.style("fill", (d) => {
return myColor;
})
.style("stroke-width", 4)
.style("stroke", "none")
.style("opacity", 0.8)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave);
}
);
// Add title to graph
svg
.append("text")
.attr("x", 0)
.attr("y", -50)
.attr("text-anchor", "left")
.style("font-size", "22px")
.text("A d3.js heatmap");
// Add subtitle to graph
svg
.append("text")
.attr("x", 0)
.attr("y", -20)
.attr("text-anchor", "left")
.style("font-size", "14px")
.style("fill", "grey")
.style("max-width", 400)
.text("A short description of the take-away message of this chart.");
</script>

This is another way to get the desired results
var myColor = d3.scaleSequential()
.interpolator( d3.interpolateRdYlBu)
.domain([1.37, -.81])

Related

How do I plot a scatterplot with this kind of dataset?

I am a complete beginner of Javascript and D3. Currently I have been trying to create a scatterplot with x-axis showing the years and percentiles for every year and y-axis showing the values for 3 variables. But I cannot seem to get my code running. Please help.
This is the excerpt of the dataset I have now:
country_code,year,welfare_type,percentile,avg_welfare,pop_share,welfare_share
AUS,2014,income,1,2.706183088,0.009969853,4.13E-04
AUS,2014,income,2,11.03834646,0.010027236,0.001695224
AUS,2014,income,3,15.21296516,0.009923341,0.002312137
AUS,2014,income,4,17.78666642,0.009876024,0.00269041
AUS,2014,income,5,19.65899193,0.009817937,0.002956128
AUS,2014,income,6,21.23338101,0.010270198,0.003339948
AUS,2014,income,7,22.71642933,0.010107506,0.003516624
AUS,2014,income,8,23.88424149,0.010001223,0.003658528
AUS,2014,income,9,24.95633096,0.009820398,0.003753631
AUS,2014,income,10,25.78625374,0.010083031,0.003982182
AUS,2014,income,11,26.61719414,0.00994973,0.004056163
AUS,2014,income,12,27.43463276,0.010096198,0.004242275
AUS,2014,income,13,28.31720791,0.010045165,0.004356616
AUS,2014,income,14,29.23106771,0.009896533,0.004430671
AUS,2014,income,16,30.55067193,0.009863549,0.004615256
AUS,2014,income,15,29.89843511,0.010094814,0.004622624
AUS,2014,income,17,31.20316268,0.010020247,0.004788713
AUS,2014,income,19,32.38771182,0.009888694,0.004905248
AUS,2014,income,18,31.82871304,0.010124787,0.004935677
AUS,2014,income,20,32.95847038,0.00998462,0.005040114
AUS,2014,income,21,33.6474718,0.010047902,0.00517809
AUS,2014,income,22,34.33875307,0.010052882,0.005287092
AUS,2014,income,23,35.01464846,0.0099175,0.005318556
AUS,2014,income,24,35.63748207,0.010094145,0.005509578
AUS,2014,income,26,37.03581494,0.009755934,0.005533916
AUS,2014,income,25,36.26642742,0.009996408,0.005552525
AUS,2014,income,28,38.23585461,0.009992649,0.00585185
AUS,2014,income,29,38.94099912,0.009912763,0.005912125
AUS,2014,income,27,37.61468566,0.010266587,0.005914599
AUS,2014,income,30,39.66490264,0.010092823,0.006131417
AUS,2014,income,31,40.37644593,0.009921456,0.006135434
AUS,2014,income,32,41.02135057,0.00998833,0.006275446
AUS,2014,income,34,42.01105027,0.009758772,0.006279145
AUS,2014,income,33,41.62407432,0.010037465,0.006398975
AUS,2014,income,36,43.03352375,0.010044596,0.006620354
AUS,2014,income,37,43.59007717,0.009950045,0.00664285
AUS,2014,income,35,42.4723306,0.010237364,0.006659414
AUS,2014,income,38,44.05401838,0.009974684,0.006730177
AUS,2014,income,39,44.59078719,0.010080713,0.006884592
AUS,2014,income,40,45.22011959,0.010009614,0.006932515
AUS,2014,income,41,45.78335857,0.009937155,0.006968054
AUS,2014,income,42,46.49121536,0.010059652,0.007163011
AUS,2014,income,44,47.72893726,0.009855791,0.007204686
AUS,2014,income,43,47.10222632,0.010004851,0.007217617
AUS,2014,income,46,48.96673209,0.009786594,0.007339635
AUS,2014,income,45,48.31298287,0.010139416,0.007502717
AUS,2014,income,47,49.62708527,0.010060983,0.007647174
AUS,2014,income,49,51.09694646,0.009849214,0.00770794
AUS,2014,income,48,50.38862979,0.010149339,0.007832711
AUS,2014,income,50,51.83564211,0.010094099,0.008013788
AUS,2014,income,51,52.57598103,0.01003079,0.008077265
AUS,2014,income,52,53.44639201,0.010033813,0.00821346
AUS,2014,income,53,54.36172111,0.009865484,0.008213976
AUS,2014,income,54,55.3113642,0.01011584,0.008569552
AUS,2014,income,55,56.25654416,0.009960817,0.008582421
AUS,2014,income,56,57.0291785,0.009991576,0.008727159
AUS,2014,income,57,57.94137541,0.009839134,0.008731472
AUS,2014,income,58,58.59715086,0.009916506,0.008899733
AUS,2014,income,60,60.15320318,0.010046913,0.00925621
AUS,2014,income,59,59.28244241,0.01025988,0.009315586
AUS,2014,income,61,61.24756855,0.009985114,0.009366636
AUS,2014,income,62,62.45605758,0.010001891,0.0095675
AUS,2014,income,63,63.53518536,0.010014243,0.009744829
AUS,2014,income,64,64.52243794,0.00991656,0.009799718
AUS,2014,income,66,66.6700305,0.009775673,0.009982036
AUS,2014,income,65,65.58589209,0.010078047,0.010123451
AUS,2014,income,68,68.73954583,0.010002134,0.010530309
AUS,2014,income,67,67.67139554,0.010204008,0.01057591
AUS,2014,income,69,69.68166938,0.009959784,0.010629437
AUS,2014,income,70,70.78054852,0.009890164,0.01072159
AUS,2014,income,72,73.10381941,0.009986389,0.011181249
AUS,2014,income,71,71.82035176,0.010175222,0.011192657
AUS,2014,income,73,74.50528527,0.010016861,0.011430376
AUS,2014,income,74,75.81199845,0.009955876,0.011560037
AUS,2014,income,75,77.04250182,0.010042825,0.011850264
AUS,2014,income,76,78.565506,0.009955459,0.011979398
AUS,2014,income,77,80.40478014,0.009977753,0.012287298
AUS,2014,income,78,82.12333785,0.010043796,0.012632993
AUS,2014,income,79,83.79248925,0.009988891,0.012819295
AUS,2014,income,80,85.55768023,0.009991496,0.013092763
AUS,2014,income,81,87.47915,0.010038706,0.013450056
AUS,2014,income,82,89.38254022,0.009986228,0.013670864
AUS,2014,income,83,91.63481485,0.009953002,0.013968713
AUS,2014,income,84,93.91744067,0.010000544,0.01438506
AUS,2014,income,85,96.41946083,0.01005068,0.014842324
AUS,2014,income,86,99.54540544,0.009921946,0.015127246
AUS,2014,income,87,102.9654549,0.010061255,0.015866659
AUS,2014,income,88,105.971401,0.010025493,0.016271822
AUS,2014,income,89,109.1419537,0.009901563,0.016551497
AUS,2014,income,90,112.514213,0.009965222,0.017172604
AUS,2014,income,91,116.3289357,0.010076984,0.017953955
AUS,2014,income,92,120.6459775,0.01006046,0.018589704
AUS,2014,income,93,125.5685177,0.009956968,0.019149158
AUS,2014,income,94,131.9060045,0.010046029,0.020295548
AUS,2014,income,95,139.9451658,0.009996381,0.021426068
AUS,2014,income,96,148.6943539,0.009975502,0.022718048
AUS,2014,income,97,161.3097917,0.009998721,0.024702846
AUS,2014,income,98,181.7236599,0.010022054,0.027893949
AUS,2014,income,99,217.7250904,0.009993702,0.033325498
AUS,2014,income,100,419.3771126,0.010014813,0.064326418
AUS,2016,income,1,2.921344881,0.009891044,4.53E-04
AUS,2016,income,2,10.86946963,0.009887197,0.001684881
AUS,2016,income,3,14.96556705,0.010220573,0.002398038
AUS,2016,income,4,17.41174479,0.009960163,0.00271892
AUS,2016,income,5,18.84613732,0.009949316,0.002939701
AUS,2016,income,6,20.38088749,0.010060453,0.00321461
AUS,2016,income,7,21.94488945,0.009988179,0.003436429
AUS,2016,income,8,22.9706105,0.010022147,0.003609283
AUS,2016,income,10,25.00293992,0.009354153,0.003666766
AUS,2016,income,9,24.0096397,0.009995351,0.003762455
AUS,2016,income,12,26.62725434,0.009971033,0.004162499
AUS,2016,income,13,27.3528324,0.010032514,0.00430229
AUS,2016,income,11,25.76408298,0.010652475,0.004302817
AUS,2016,income,14,28.17373116,0.009973422,0.004405307
AUS,2016,income,15,29.05679359,0.00986932,0.004495961
AUS,2016,income,16,29.93744756,0.010155514,0.004766551
AUS,2016,income,17,30.59293397,0.010010156,0.004801197
AUS,2016,income,18,31.20220578,0.010001867,0.004892761
AUS,2016,income,19,31.63021913,0.009993163,0.00495556
AUS,2016,income,20,32.32867948,0.010001634,0.005069283
AUS,2016,income,21,33.06058859,0.01000566,0.005186136
AUS,2016,income,22,33.67194926,0.009929743,0.005241962
AUS,2016,income,23,34.30940692,0.010074751,0.005419199
AUS,2016,income,24,34.84748724,0.009926655,0.005423279
AUS,2016,income,25,35.29368138,0.009943476,0.005502028
AUS,2016,income,27,36.74800232,0.009728971,0.005605163
AUS,2016,income,26,35.97401424,0.010091598,0.005691627
AUS,2016,income,29,38.19577669,0.009894985,0.005925406
AUS,2016,income,28,37.45386648,0.010306717,0.006052079
AUS,2016,income,30,38.83223624,0.010107443,0.006153488
AUS,2016,income,31,39.40745425,0.009980666,0.006166312
AUS,2016,income,32,40.10945618,0.009983972,0.006278238
AUS,2016,income,33,40.78564161,0.00995818,0.006367587
AUS,2016,income,35,41.63865286,0.009996976,0.006526088
AUS,2016,income,34,41.39825541,0.010074415,0.006538671
AUS,2016,income,36,42.02093891,0.009971631,0.006569307
AUS,2016,income,37,42.62393647,0.010025866,0.006699819
AUS,2016,income,38,43.26897405,0.009984334,0.006773034
AUS,2016,income,39,43.95228489,0.009974039,0.006872902
AUS,2016,income,40,44.61490953,0.010040435,0.007022959
AUS,2016,income,41,45.37646989,0.009964403,0.007088749
AUS,2016,income,42,45.97395005,0.010033745,0.007232068
AUS,2016,income,43,46.65105029,0.009968655,0.007290975
AUS,2016,income,46,48.73932332,0.009553738,0.007300295
AUS,2016,income,44,47.42866471,0.010030614,0.007458578
AUS,2016,income,45,48.02211222,0.009979524,0.007513438
AUS,2016,income,48,50.01934665,0.009986286,0.007831224
AUS,2016,income,49,50.72917496,0.010008305,0.007959869
AUS,2016,income,50,51.46537181,0.010003591,0.008071582
AUS,2016,income,47,49.36311865,0.010466048,0.008099774
AUS,2016,income,51,52.29708356,0.009965039,0.008170414
AUS,2016,income,52,53.21992628,0.009944834,0.008297732
AUS,2016,income,53,53.94076603,0.010028668,0.008481017
AUS,2016,income,54,54.73058001,0.010073508,0.008643675
AUS,2016,income,55,55.66432548,0.009998435,0.008725626
AUS,2016,income,56,56.71593196,0.009997721,0.008889835
AUS,2016,income,58,58.50555862,0.009824501,0.009011461
AUS,2016,income,57,57.57195448,0.009994539,0.009021138
AUS,2016,income,59,59.45792769,0.010138709,0.009451049
AUS,2016,income,60,60.62677419,0.01000758,0.009512204
AUS,2016,income,61,61.80787097,0.00992854,0.009620924
AUS,2016,income,63,63.43629548,0.009874096,0.009820255
AUS,2016,income,62,62.54525396,0.010092093,0.009896081
AUS,2016,income,64,64.60173999,0.010140293,0.010270281
AUS,2016,income,65,65.60493276,0.009991716,0.010276948
AUS,2016,income,66,66.72095274,0.0100073,0.010468074
AUS,2016,income,67,67.93312637,0.009973639,0.010622405
AUS,2016,income,68,69.29769991,0.009953586,0.010813991
AUS,2016,income,69,70.61850675,0.010067056,0.011145732
AUS,2016,income,70,71.88259924,0.010003244,0.01127333
AUS,2016,income,71,73.1759581,0.009903166,0.011361353
AUS,2016,income,73,75.68829689,0.009855145,0.011694438
AUS,2016,income,72,74.49065685,0.010101602,0.01179722
AUS,2016,income,74,76.93036571,0.009955659,0.012007578
AUS,2016,income,77,81.22701085,0.009611704,0.012240199
AUS,2016,income,75,78.2816762,0.010156349,0.012464801
AUS,2016,income,76,79.70407585,0.01002164,0.012522958
AUS,2016,income,79,84.38656413,0.009776858,0.012934814
AUS,2016,income,78,82.90435259,0.010162592,0.013208984
AUS,2016,income,81,88.14204825,0.009881302,0.013654787
AUS,2016,income,80,85.99034668,0.010424978,0.014054405
AUS,2016,income,82,89.83042069,0.010017994,0.014108856
AUS,2016,income,83,91.3544176,0.010030154,0.014365632
AUS,2016,income,84,93.16756247,0.010100337,0.014753267
AUS,2016,income,85,95.15888443,0.009933997,0.014820436
AUS,2016,income,86,97.77003411,0.010059915,0.015420118
AUS,2016,income,87,100.7484106,0.009970617,0.015748813
AUS,2016,income,88,103.3231109,0.010040767,0.016264921
AUS,2016,income,89,106.4835939,0.009997772,0.016690661
AUS,2016,income,90,109.9008807,0.009943091,0.017132083
AUS,2016,income,91,113.327115,0.01006132,0.01787625
AUS,2016,income,92,117.2869678,0.009933027,0.01826497
AUS,2016,income,93,121.4394061,0.009984393,0.019009422
AUS,2016,income,94,126.5037933,0.010056994,0.019946163
AUS,2016,income,95,133.7253411,0.010013734,0.020994106
AUS,2016,income,96,142.5918642,0.009978695,0.022307768
AUS,2016,income,97,153.5144822,0.009931858,0.023903829
AUS,2016,income,98,170.2017432,0.010084885,0.026910549
AUS,2016,income,99,208.2369816,0.010000861,0.032649976
AUS,2016,income,100,360.2167398,0.010018403,0.056578312
AUS,2018,income,1,2.595366313,0.009842698,3.95E-04
AUS,2018,income,2,9.823911429,0.010133857,0.001540855
AUS,2018,income,3,14.02903825,0.010019847,0.002175663
AUS,2018,income,4,16.20475069,0.00999557,0.00250699
AUS,2018,income,5,18.10915852,0.00998426,0.002798445
AUS,2018,income,6,19.9508763,0.00993849,0.003068916
AUS,2018,income,7,21.28037443,0.009700865,0.003195158
AUS,2018,income,8,22.46745331,0.010256684,0.003566674
AUS,2018,income,9,23.58626711,0.010043957,0.003666627
AUS,2018,income,10,24.56020059,0.009778468,0.00371711
AUS,2018,income,11,25.42979959,0.010202929,0.004015785
AUS,2018,income,12,26.33331407,0.010042599,0.004093118
AUS,2018,income,13,27.40014618,0.010006882,0.004243794
AUS,2018,income,14,28.52270694,0.009951873,0.004393375
AUS,2018,income,15,29.52728239,0.010003639,0.004571767
AUS,2018,income,16,30.26886102,0.009941065,0.004657272
AUS,2018,income,17,31.05298971,0.010123957,0.004865824
AUS,2018,income,18,31.98053166,0.010029435,0.004964377
AUS,2018,income,20,33.22802717,0.009797099,0.00503854
AUS,2018,income,19,32.66549084,0.009992269,0.005051914
AUS,2018,income,21,33.63693313,0.010003789,0.005208151
AUS,2018,income,25,36.01406074,0.009539114,0.005317198
AUS,2018,income,22,34.17025041,0.010130968,0.005357988
AUS,2018,income,23,34.82676969,0.010063973,0.00542482
AUS,2018,income,24,35.36869964,0.010013115,0.005481393
AUS,2018,income,27,37.20731631,0.009821302,0.005655879
AUS,2018,income,33,40.87633985,0.009210976,0.005827474
AUS,2018,income,26,36.50531459,0.01045545,0.005907469
AUS,2018,income,28,37.85771532,0.010182103,0.005966155
AUS,2018,income,29,38.61389827,0.010002608,0.00597805
AUS,2018,income,30,39.23941491,0.009962674,0.006050637
AUS,2018,income,31,39.93717676,0.010022552,0.006195243
AUS,2018,income,32,40.47103984,0.009980693,0.006251838
AUS,2018,income,36,42.40615011,0.009803519,0.006434481
AUS,2018,income,35,41.79732628,0.010157682,0.006571216
AUS,2018,income,39,44.29336043,0.009680314,0.006636372
AUS,2018,income,38,43.63415757,0.010038815,0.006779719
AUS,2018,income,37,43.06505422,0.010175109,0.00678214
AUS,2018,income,34,41.19537868,0.010642366,0.006785617
AUS,2018,income,41,45.31986066,0.009964569,0.006989558
AUS,2018,income,40,44.78770392,0.010220832,0.007085128
AUS,2018,income,42,45.98918996,0.010131453,0.007211575
AUS,2018,income,43,46.75184156,0.009979741,0.007221388
AUS,2018,income,44,47.49359156,0.009980116,0.007336236
AUS,2018,income,45,48.33259569,0.010048654,0.007517106
AUS,2018,income,46,49.07601632,0.009919118,0.007534337
AUS,2018,income,47,49.90985642,0.0100312,0.007748932
AUS,2018,income,48,50.82979576,0.010008184,0.007873654
AUS,2018,income,49,51.65939593,0.009968356,0.007970316
AUS,2018,income,50,52.49251803,0.009898442,0.008042053
AUS,2018,income,52,53.87597193,0.0099824,0.008324013
AUS,2018,income,51,53.27500401,0.010125596,0.008349236
AUS,2018,income,53,54.62220616,0.009877231,0.008350397
AUS,2018,income,54,55.47221646,0.009776907,0.008394207
AUS,2018,income,55,56.23253556,0.010238282,0.008910815
AUS,2018,income,56,57.24371642,0.010085894,0.008936035
AUS,2018,income,58,59.10520774,0.009834502,0.008996649
AUS,2018,income,57,58.16688376,0.010051726,0.009049385
AUS,2018,income,60,60.91533476,0.009875512,0.009310841
AUS,2018,income,59,59.90437715,0.010183559,0.009441931
AUS,2018,income,61,61.75432927,0.009958307,0.009518217
AUS,2018,income,62,62.61595691,0.010139702,0.009826817
AUS,2018,income,63,63.64261438,0.010040373,0.009890097
AUS,2018,income,64,64.68995889,0.00999147,0.01000389
AUS,2018,income,65,65.87401702,0.009953768,0.010148557
AUS,2018,income,68,68.91650916,0.009713594,0.0103611
AUS,2018,income,66,66.8617044,0.01005883,0.010409445
AUS,2018,income,67,67.79991077,0.009982134,0.010475027
AUS,2018,income,70,70.96026521,0.009908804,0.010882762
AUS,2018,income,69,70.000275,0.010239873,0.011094225
AUS,2018,income,71,72.26105558,0.010004988,0.011189831
AUS,2018,income,72,73.60416061,0.010107856,0.011515003
AUS,2018,income,73,74.84108522,0.010028489,0.011616578
AUS,2018,income,74,76.30553539,0.009972862,0.011778189
AUS,2018,income,75,77.63277599,0.009953914,0.011960288
AUS,2018,income,76,78.97379055,0.010069723,0.012308445
AUS,2018,income,77,80.61337965,0.00997618,0.012447268
AUS,2018,income,78,82.35020384,0.010030576,0.012784779
AUS,2018,income,79,83.8521037,0.009943725,0.012905229
AUS,2018,income,80,85.3092945,0.010001952,0.013206379
AUS,2018,income,81,86.82983593,0.009983915,0.013417528
AUS,2018,income,82,88.95395683,0.009973547,0.013731487
AUS,2018,income,83,90.96324283,0.009967333,0.014032905
AUS,2018,income,84,93.16888148,0.010097804,0.01456131
I want the year and percentile attributes on the x-axis and divide the y-axis into three sections: avg_welfare, welfare_share and pop_share.
This is the current code I have, but nothing is showing on my browser. What is wrong with the code?
<!DOCTYPE html>
<html lang="en">
<body>
<svg width="1000" height="1000"></svg>
<script src="https://d3js.org/d3.v4.js" charset="utf-8">
var margin = {top:100, right:80, bottom:80, left:80};
//Setting attributes of SVG
var svg = d3.select("body")
.append("svg")
//Setting attribute width and height as numbers instead of strings
var width = parseInt(svg.attr('width'));
var height = parseInt(svg.attr("height"));
svg.attr("width", width + margin.left + margin.right);
svg.attr("height", height + margin.top + margin.bottom);
//Setting attributes of x-axis
var xaxis = d3.append("g")
.attr("transform", "translate(0, " + height + ")")
.scaleBand()
//Setting attributes of y-axis
var yaxis = d3.append("g")
.scaleLinear()
//Extracting data
d3.csv("data/programmingassignment1data.csv", function(error, data){
if (error) throw error;
data.forEach(function(d){
d.year = +d.year
d.percentile = +d.percentile
d.avg_welfare = +d.avg_welfare
d.pop_share = +d.pop_share
d.welfare_share = +d.welfare_share
})
//Drawing x-axis
var x1 = xaxis.domain(data.map(function(d) {return d.year}))
.range([margin.left, width]).padding(0.4)
.call(d3.axisBottom(x1))
var x2 = xaxis.domain(data.map(function(d) {return d.percentile}))
.range([margin.left, width/5]).padding(0.4)
.call(d3.axisBottom(x2))
var x3 = xaxis.domain(data.map(function(d) {return d.percentile}))
.range([width/5, width*2/5]).padding(0.4)
.call(d3.axisBottom(x3))
var x4 = xaxis.domain(data.map(function(d) {return d.percentile}))
.range([width*2/5, width*3/5]).padding(0.4)
.call(d3.axisBottom(x4))
var x5 = xaxis.domain(data.map(function(d) {return d.percentile}))
.range([width*3/5, width*4/5]).padding(0.4)
.call(d3.axisBottom(x5))
var x6 = xaxis.domain(data.map(function(d) {return d.percentile}))
.range([width*4/5, width]).padding(0.4)
.call(d3.axisBottom(x6))
//Drawing y-axis
var y1 = yaxis.domain([d3.max(data, function(d) {return d.avg_welfare}), 0])
.range([height, height/3]).padding(0.4)
.call(d3.axisLeft(y1))
var y2 = yaxis.domain([d3.max(data, function(d) {return d.welfare_share}), 0])
.range([height/3, height*2/3]).padding(0.4)
.call(d3.axisLeft(y2))
var y3 = yaxis.domain([d3.max(data, function(d) {return d.pop_share}), 0])
.range([height*2/3, 0]).padding(0.4)
.call(d3.axisLeft(y3))
//Setting scatterplot attributes
var g = svg.append("g")
.selectAll("dot")
.data(data)
.enter()
.append("circle")
//Plotting scatterplots
var g1 = g.attr("cx", function(d) {return x1(d.year); })
.attr("cy", function(d) {return y1(d.avg_welfare); })
.attr("r", 5)
.style("fill", "green")
var g2 = g.attr("cx", function(d) {return x1(d.year); })
.attr("cy", function(d) {return y2(d.welfare_share); })
.attr("r", 5)
.style("fill", "blue")
var g3 = g.attr("cx", function(d) {return x1(d.year); })
.attr("cy", function(d) {return y3(d.pop_share); })
.attr("r", 5)
.style("fill", "yellow")
//Adding chart title
svg.append("text")
.attr("transform", "translate(300,0)")
.attr("x", 50)
.attr("y", 50)
.attr("font-size", "40px")
.text("Distribution of wealth from 2014-2018");
//Adding data and axis labels
var gxLabels = svg.append("g")
.attr("transform", "translate(0, " + (height + margin.top + 40) + ")")
.append("text")
.attr("y", 20)
.attr("x", margin.left + width/2)
.attr("text-anchor", "end")
.attr("stroke", "black")
.text("Year");
var gyLabels = svg.append("g")
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 30)
.attr("dy", "-5.1em")
.attr("text-anchor", "end")
.attr("stroke", "black");
gyLabels.attr('transform', 'translate(' + margin.left + ', ' + (margin.top + 0 * height / 3) + ')')
.text("Average Wealth");
gyLabels.attr('transform', 'translate(' + margin.left + ', ' + (margin.top + 1 * height / 3) + ')')
.text("Share of Wealth");
gyLabels.attr('transform', 'translate(' + margin.left + ', ' + (margin.top + 2 * height / 3) + ')')
.text("Population Share")
});
</script>
</body>
Here is a working version that produces a stacked scatter plot.
<!DOCTYPE html>
<html lang="en">
<body>
<!-- CORRECTION: you cannot place your SVG inside the script tag -->
<svg width="1000" height="1000"></svg>
<script src="https://d3js.org/d3.v4.js" charset="utf-8">
</script>
<script>
// CORRECTION: Added more margin to fit all axes
var margin = {top:100, right:30, bottom:80, left:80}
var svg = d3.select("svg")
// CORRECTION: you were trying to access width before setting it. Attributes come as strings - convert to number
var width = parseInt(svg.attr('width'));
svg.attr("width", width + margin.left + margin.right);
// CORRECTION: also add height margin
var height = parseInt(svg.attr("height"));
svg.attr('height', height + margin.top + margin.bottom);
var g =svg.append("g")
d3.csv("Data/programmingassignment1data.csv", function(error, data){
if (error) throw error;
data.forEach(function(d){
d.year = +d.year
d.percentile = +d.percentile
d.avg_welfare = +d.avg_welfare
d.pop_share = +d.pop_share
d.welfare_share = +d.welfare_share
});
var xAxis1 = d3.scaleBand()
.domain(data.map(function(d) {return d.year}))
.range([margin.left, width]).padding(0.4);
var xAxis2 = d3.scaleBand()
.domain(data.map(function(d) {return d.percentile}))
// CORRECTION: this need to be the same as the other x-Axis. Range is the area of the viewport
.range([margin.left, width]).padding(0.4);
var yAxis1 = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {return d.avg_welfare})])
.range([margin.top + 0 * height / 3, margin.top + 1 * height / 3]);
var yAxis2 = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {return d.welfare_share})])
.range([margin.top + 1 * height / 3, margin.top + 2 * height / 3]);
var yAxis3 = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {return d.pop_share})])
.range([margin.top + 2 * height / 3, margin.top + 3 * height / 3]);
g.append("g")
.attr("transform", "translate(0, " + (height + margin.top + 0) + ")")
.call(d3.axisBottom(xAxis1))
g.append("g")
.attr("transform", "translate(0, " + (height + margin.top + 20) + ")")
.call(d3.axisBottom(xAxis2))
g.append("g")
// CORRECTION: move axis by margin
.attr('transform', 'translate(' + margin.left + ' 0)')
.call(d3.axisLeft(yAxis1))
g.append("g")
// CORRECTION: move axis by margin
.attr('transform', 'translate(' + margin.left + ' 0)')
.call(d3.axisLeft(yAxis2))
g.append("g")
// CORRECTION: move axis by margin
.attr('transform', 'translate(' + margin.left + ' 0)')
.call(d3.axisLeft(yAxis3))
g.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("cx", function(d) {return xAxis1(d.year); })
.attr("cy", function(d) {return yAxis1(d.avg_welfare); })
.attr("r", 5)
.style("fill", "green")
g.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("cx", function(d) {return xAxis1(d.year); })
.attr("cy", function(d) {return yAxis2(d.welfare_share); })
.attr("r", 5)
.style("fill", "blue")
g.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("cx", function(d) {return xAxis1(d.year); })
.attr("cy", function(d) {return yAxis3(d.pop_share); })
.attr("r", 5)
.style("fill", "yellow")
svg.append("text")
.attr("transform", "translate(300,0)")
.attr("x", 50)
.attr("y", 50)
.attr("font-size", "40px")
.text("Distribution of wealth from 2014-2018");
g.append("g")
.attr("transform", "translate(0, " + (height + margin.top + 40) + ")")
// .call(d3.axisBottom(xAxis1)) - CORRECTION: This draws the actual axes. You have done this already
.append("text")
// CORRECTION: the x/y of the text is added to the existing translation of the group
.attr("y", 20)
.attr("x", margin.left + width)
.attr("text-anchor", "end")
.attr("stroke", "black")
.text("Year");
g.append("g")
// CORRECTION: - transform into view (margins)
.attr('transform', 'translate(' + margin.left + ', ' + (margin.top + 0 * height / 3) + ')')
// .call(d3.axisLeft(yAxis1)) - CORRECTION: This draws the actual axes. You have done this already
.append("text")
.attr("transform", "rotate(-90)")
// CORRECTION: - moved into view - horizontal placement after rotation
.attr("y", 30)
.attr("dy", "-5.1em")
.attr("text-anchor", "end")
.attr("stroke", "black")
.text("Average Wealth");
g.append("g")
// CORRECTION: - transform into view (margins)
.attr('transform', 'translate(' + margin.left + ', ' + (margin.top + 1 * height / 3) + ')')
// .call(d3.axisLeft(yAxis2)) - CORRECTION: This draws the actual axes. You have done this already
.append("text")
.attr("transform", "rotate(-90)")
// CORRECTION: - moved into view - horizontal placement after rotation
.attr("y", 30)
.attr("dy", "-5.1em")
.attr("text-anchor", "end")
.attr("stroke", "black")
.text("Share of Wealth");
g.append("g")// CORRECTION: - transform into view (margins)
.attr('transform', 'translate(' + margin.left + ', ' + (margin.top + 2 * height / 3) + ')')
// .call(d3.axisLeft(yAxis3)) - CORRECTION: This draws the actual axes. You have done this already
.append("text")
.attr("transform", "rotate(-90)")
// CORRECTION: - moved into view - horizontal placement after rotation
.attr("y", 30)
.attr("dy", "-5.1em")
.attr("text-anchor", "end")
.attr("stroke", "black")
.text("Population Share")
});
</script>
</body>
There were some errors in the script tags.
For further improving the solution I would suggest:
Do not call you scale functions (i.e. scaleLinear()) 'axis'. An axis is a way of visualizing a scale. Just call them x1, x2, y1, etc. d3.axisLeft() is the command for drawing the axes for a given scale.
Work with SVG groups (g). When you transform a g element, the placement of all children will be relative to its origin. You could create a single SVG g element for all three stacked charts and translate them vertically. Have a look at this example of stacking charts.

D3js: How do I make my tooltip appear next to the selection?

I am trying to have a tooltip for each square on my heatmap visualization. However, I am not able to position it next to the cursor correctly. This is what happens:
My code is this:
const margin = {
top: 20,
right: 20,
bottom: 30,
left: 150,
};
const width = 960 - margin.left - margin.right;
const height = 2500 - margin.top - margin.bottom;
let chart = d3
.select("#chart2")
.append("div")
// Set id to chartArea
.attr("id", "chartArea")
.classed("chart", true)
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Make sure to create a separate SVG for the XAxis
let axis = d3
.select("#chart2")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", 40)
.append("g")
.attr("transform", "translate(" + margin.left + ", 0)");
// Load the data
d3.csv("https://raw.githubusercontent.com/thedivtagguy/files/main/land_use.csv").then(function(data) {
// console.log(data);
const years = Array.from(new Set(data.map((d) => d.year)));
const countries = Array.from(new Set(data.map((d) => d.entity)));
countries.reverse();
const x = d3.scaleBand().range([0, width]).domain(years).padding(0.01);
// create a tooltip
var tooltip = d3
// Select all boxes in the chart
.select("#chart2")
.append("div")
.classed("tooltip", true)
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px");
const mouseover = function(event, d) {
tooltip.style("opacity", 1);
d3.select(this).style("stroke", "black").style("opacity", 1);
};
const mousemove = function(event, d) {
tooltip
.html("The exact value of<br>this cell is: " + d.value)
// Position the tooltip next to the cursor
.style("left", event.x + "px")
.style("top", event.y / 2 + "px");
};
const mouseleave = function(event, d) {
tooltip.style("opacity", 0);
d3.select(this).style("stroke", "none").style("opacity", 0.8);
};
const y = d3.scaleBand().range([height, 0]).domain(countries).padding(0.01);
// Only 10 years
axis
.call(d3.axisBottom(x).tickValues(years.filter((d, i) => !(i % 10))))
.selectAll("text")
.style("color", "black")
.style("position", "fixed")
.attr("transform", "translate(-10,10)rotate(-45)")
.style("text-anchor", "end");
chart
.append("g")
.call(d3.axisLeft(y))
.selectAll("text")
.style("color", "black")
.attr("transform", "translate(-10,0)")
.style("text-anchor", "end");
const colorScale = d3
.scaleSequential()
.domain([0, d3.max(data, (d) => d.change)])
.interpolator(d3.interpolateInferno);
// add the squares
chart
.selectAll()
.data(data, function(d) {
return d.year + ":" + d.entity;
})
.join("rect")
// Add id-s
.attr("id", function(d) {
return d.year + ":" + d.entity;
})
.attr("x", function(d) {
return x(d.year);
})
.attr("y", function(d) {
return y(d.entity);
})
.attr("width", x.bandwidth())
.attr("height", y.bandwidth())
.style("fill", function(d) {
return colorScale(d.change);
console.log(d.change);
})
.style("stroke-width", 4)
.style("stroke", "none")
.style("opacity", 0.8)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave);
});
#chart2 .chart {
width: 960px;
max-height: 900px;
overflow-y: scroll;
overflow-x: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<div id="chart2" class="mx-auto"></div>
I think I have some idea of why this is happening. Since I am appending the tooltip iv to chart2 div like this, all positioning is happening relative to that div, which means it'll inevitably be below the entire chart and not on top of it:
// create a tooltip
var tooltip = d3
// Select all boxes in the chart
.select("#chart2")
.append("div")
.classed("tooltip", true)
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px");
const mousemove = function(event, d) {
tooltip
.html("The exact value of<br>this cell is: " + d.value)
// Position the tooltip next to the cursor
.style("left", event.x + "px")
.style("top", event.y / 2 + "px");
};
But how else would I do this? I have tried trying to select by the hovered-on rect element but that hasn't been working. I am trying to do something like this.
How can I fix this?
A live version can be found here
Just add in the mousemove function .style("position","absolute"); and change top style to .style("top", event.y + "px")
const margin = {
top: 20,
right: 20,
bottom: 30,
left: 150,
};
const width = 960 - margin.left - margin.right;
const height = 2500 - margin.top - margin.bottom;
let chart = d3
.select("#chart2")
.append("div")
// Set id to chartArea
.attr("id", "chartArea")
.classed("chart", true)
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Make sure to create a separate SVG for the XAxis
let axis = d3
.select("#chart2")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", 40)
.append("g")
.attr("transform", "translate(" + margin.left + ", 0)");
// Load the data
d3.csv("https://raw.githubusercontent.com/thedivtagguy/files/main/land_use.csv").then(function(data) {
// console.log(data);
const years = Array.from(new Set(data.map((d) => d.year)));
const countries = Array.from(new Set(data.map((d) => d.entity)));
countries.reverse();
const x = d3.scaleBand().range([0, width]).domain(years).padding(0.01);
// create a tooltip
var tooltip = d3
// Select all boxes in the chart
.select("#chart2")
.append("div")
.classed("tooltip", true)
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px");
const mouseover = function(event, d) {
tooltip.style("opacity", 1);
d3.select(this).style("stroke", "black").style("opacity", 1);
};
const mousemove = function(event, d) {
tooltip
.html("The exact value of<br>this cell is: " + d.value)
// Position the tooltip next to the cursor
.style("left", event.x + "px")
.style("top", event.y + "px")
.style("position","absolute");
};
const mouseleave = function(event, d) {
tooltip.style("opacity", 0);
d3.select(this).style("stroke", "none").style("opacity", 0.8);
};
const y = d3.scaleBand().range([height, 0]).domain(countries).padding(0.01);
// Only 10 years
axis
.call(d3.axisBottom(x).tickValues(years.filter((d, i) => !(i % 10))))
.selectAll("text")
.style("color", "black")
.style("position", "fixed")
.attr("transform", "translate(-10,10)rotate(-45)")
.style("text-anchor", "end");
chart
.append("g")
.call(d3.axisLeft(y))
.selectAll("text")
.style("color", "black")
.attr("transform", "translate(-10,0)")
.style("text-anchor", "end");
const colorScale = d3
.scaleSequential()
.domain([0, d3.max(data, (d) => d.change)])
.interpolator(d3.interpolateInferno);
// add the squares
chart
.selectAll()
.data(data, function(d) {
return d.year + ":" + d.entity;
})
.join("rect")
// Add id-s
.attr("id", function(d) {
return d.year + ":" + d.entity;
})
.attr("x", function(d) {
return x(d.year);
})
.attr("y", function(d) {
return y(d.entity);
})
.attr("width", x.bandwidth())
.attr("height", y.bandwidth())
.style("fill", function(d) {
return colorScale(d.change);
console.log(d.change);
})
.style("stroke-width", 4)
.style("stroke", "none")
.style("opacity", 0.8)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave);
});
#chart2 .chart {
width: 960px;
max-height: 900px;
overflow-y: scroll;
overflow-x: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<div id="chart2" class="mx-auto"></div>

Page displaying only 1 of 2 charts

In this codepen I am trying to create 2 treemaps with D3.js but only the second treemap gets displayed. When I check the elements in the console I can see the 2 different svg's are created and written to the DOM but only the second "g" tag is populated with the SVG rect elements. There are 2 distinct div tags with distinct id's. How can I draw 2 D3.sj treemaps on side by side? Thank you.
D3.js code
var margin = {top: 10, right: 10, bottom: 10, left: 10},
width = 445 - margin.left - margin.right,
height = 445 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz1")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// read json data
d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_dendrogram_full.json", function(data) {
// Give the data to this cluster layout:
var root = d3.hierarchy(data).sum(function(d){ return d.value}) // Here the size of each leave is given in the 'value' field in input data
// Then d3.treemap computes the position of each element of the hierarchy
d3.treemap()
.size([width, height])
.paddingTop(28)
.paddingRight(7)
.paddingInner(3) // Padding between each rectangle
//.paddingOuter(6)
//.padding(20)
(root)
// prepare a color scale
var color = d3.scaleOrdinal()
.domain(["source1", "source2", "source3"])
.range([ "#402D54", "#D18975", "#8FD175"])
// And a opacity scale
var opacity = d3.scaleLinear()
.domain([10, 30])
.range([.5,1])
// use this information to add rectangles:
svg
.selectAll("rect")
.data(root.leaves())
.enter()
.append("rect")
.attr('x', function (d) { return d.x0; })
.attr('y', function (d) { return d.y0; })
.attr('width', function (d) { return d.x1 - d.x0; })
.attr('height', function (d) { return d.y1 - d.y0; })
.style("stroke", "black")
.style("fill", function(d){ return color(d.parent.data.name)} )
.style("opacity", function(d){ return opacity(d.data.value)})
// and to add the text labels
svg
.selectAll("text")
.data(root.leaves())
.enter()
.append("text")
.attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right)
.attr("y", function(d){ return d.y0+20}) // +20 to adjust position (lower)
.text(function(d){ return d.data.name.replace('mister_','') })
.attr("font-size", "19px")
.attr("fill", "white")
// and to add the text labels
svg
.selectAll("vals")
.data(root.leaves())
.enter()
.append("text")
.attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right)
.attr("y", function(d){ return d.y0+35}) // +20 to adjust position (lower)
.text(function(d){ return d.data.value })
.attr("font-size", "11px")
.attr("fill", "white")
// Add title for the 3 groups
svg
.selectAll("titles")
.data(root.descendants().filter(function(d){return d.depth==1}))
.enter()
.append("text")
.attr("x", function(d){ return d.x0})
.attr("y", function(d){ return d.y0+21})
.text(function(d){ return d.data.name })
.attr("font-size", "19px")
.attr("fill", function(d){ return color(d.data.name)} )
// Add title for the 3 groups
svg
.append("text")
.attr("x", 0)
.attr("y", 14) // +20 to adjust position (lower)
.text("Three group sources")
.attr("font-size", "19px")
.attr("fill", "grey" )
})
var margin = {top: 10, right: 10, bottom: 10, left: 10},
width = 445 - margin.left - margin.right,
height = 445 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz2")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// read json data
d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_dendrogram_full.json", function(data) {
// Give the data to this cluster layout:
var root = d3.hierarchy(data).sum(function(d){ return d.value}) // Here the size of each leave is given in the 'value' field in input data
// Then d3.treemap computes the position of each element of the hierarchy
d3.treemap()
.size([width, height])
.paddingTop(28)
.paddingRight(7)
.paddingInner(3) // Padding between each rectangle
//.paddingOuter(6)
//.padding(20)
(root)
// prepare a color scale
var color = d3.scaleOrdinal()
.domain(["source1", "source2", "source3"])
.range([ "#402D54", "#D18975", "#8FD175"])
// And a opacity scale
var opacity = d3.scaleLinear()
.domain([10, 30])
.range([.5,1])
// use this information to add rectangles:
svg
.selectAll("rect")
.data(root.leaves())
.enter()
.append("rect")
.attr('x', function (d) { return d.x0; })
.attr('y', function (d) { return d.y0; })
.attr('width', function (d) { return d.x1 - d.x0; })
.attr('height', function (d) { return d.y1 - d.y0; })
.style("stroke", "black")
.style("fill", function(d){ return color(d.parent.data.name)} )
.style("opacity", function(d){ return opacity(d.data.value)})
// and to add the text labels
svg
.selectAll("text")
.data(root.leaves())
.enter()
.append("text")
.attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right)
.attr("y", function(d){ return d.y0+20}) // +20 to adjust position (lower)
.text(function(d){ return d.data.name.replace('mister_','') })
.attr("font-size", "19px")
.attr("fill", "white")
// and to add the text labels
svg
.selectAll("vals")
.data(root.leaves())
.enter()
.append("text")
.attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right)
.attr("y", function(d){ return d.y0+35}) // +20 to adjust position (lower)
.text(function(d){ return d.data.value })
.attr("font-size", "11px")
.attr("fill", "white")
// Add title for the 3 groups
svg
.selectAll("titles")
.data(root.descendants().filter(function(d){return d.depth==1}))
.enter()
.append("text")
.attr("x", function(d){ return d.x0})
.attr("y", function(d){ return d.y0+21})
.text(function(d){ return d.data.name })
.attr("font-size", "19px")
.attr("fill", function(d){ return color(d.data.name)} )
// Add title for the 3 groups
svg
.append("text")
.attr("x", 0)
.attr("y", 14) // +20 to adjust position (lower)
.text("Three group sources")
.attr("font-size", "19px")
.attr("fill", "grey" )
})
.dataviz {
display: inline-block;
}
<script src="https://d3js.org/d3.v4.js"></script>
<div>
<div class="dataviz" id="my_dataviz1"></div>
<div class="dataviz" id="my_dataviz2"></div>
</div>
You have the same name for the two SVG selections:
var svg = d3.select("#my_dataviz1")//etc...
var svg = d3.select("#my_dataviz2")//etc..
The solution is quite simple, give them different names:
var svg = d3.select("#my_dataviz1")//etc...
var svg2 = d3.select("#my_dataviz2")//etc...
Finally, considering that both drawing functions do the same, consider creating a single function to which you pass the SVG selection and the data. That way, you can substantially reduce the size of your code.
Here is your code with the changes:
var margin = {top: 10, right: 10, bottom: 10, left: 10},
width = 445 - margin.left - margin.right,
height = 445 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz1")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// read json data
d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_dendrogram_full.json", function(data) {
// Give the data to this cluster layout:
var root = d3.hierarchy(data).sum(function(d){ return d.value}) // Here the size of each leave is given in the 'value' field in input data
// Then d3.treemap computes the position of each element of the hierarchy
d3.treemap()
.size([width, height])
.paddingTop(28)
.paddingRight(7)
.paddingInner(3) // Padding between each rectangle
//.paddingOuter(6)
//.padding(20)
(root)
// prepare a color scale
var color = d3.scaleOrdinal()
.domain(["source1", "source2", "source3"])
.range([ "#402D54", "#D18975", "#8FD175"])
// And a opacity scale
var opacity = d3.scaleLinear()
.domain([10, 30])
.range([.5,1])
// use this information to add rectangles:
svg
.selectAll("rect")
.data(root.leaves())
.enter()
.append("rect")
.attr('x', function (d) { return d.x0; })
.attr('y', function (d) { return d.y0; })
.attr('width', function (d) { return d.x1 - d.x0; })
.attr('height', function (d) { return d.y1 - d.y0; })
.style("stroke", "black")
.style("fill", function(d){ return color(d.parent.data.name)} )
.style("opacity", function(d){ return opacity(d.data.value)})
// and to add the text labels
svg
.selectAll("text")
.data(root.leaves())
.enter()
.append("text")
.attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right)
.attr("y", function(d){ return d.y0+20}) // +20 to adjust position (lower)
.text(function(d){ return d.data.name.replace('mister_','') })
.attr("font-size", "19px")
.attr("fill", "white")
// and to add the text labels
svg
.selectAll("vals")
.data(root.leaves())
.enter()
.append("text")
.attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right)
.attr("y", function(d){ return d.y0+35}) // +20 to adjust position (lower)
.text(function(d){ return d.data.value })
.attr("font-size", "11px")
.attr("fill", "white")
// Add title for the 3 groups
svg
.selectAll("titles")
.data(root.descendants().filter(function(d){return d.depth==1}))
.enter()
.append("text")
.attr("x", function(d){ return d.x0})
.attr("y", function(d){ return d.y0+21})
.text(function(d){ return d.data.name })
.attr("font-size", "19px")
.attr("fill", function(d){ return color(d.data.name)} )
// Add title for the 3 groups
svg
.append("text")
.attr("x", 0)
.attr("y", 14) // +20 to adjust position (lower)
.text("Three group sources")
.attr("font-size", "19px")
.attr("fill", "grey" )
})
var margin = {top: 10, right: 10, bottom: 10, left: 10},
width = 445 - margin.left - margin.right,
height = 445 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg2 = d3.select("#my_dataviz2")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// read json data
d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_dendrogram_full.json", function(data) {
// Give the data to this cluster layout:
var root = d3.hierarchy(data).sum(function(d){ return d.value}) // Here the size of each leave is given in the 'value' field in input data
// Then d3.treemap computes the position of each element of the hierarchy
d3.treemap()
.size([width, height])
.paddingTop(28)
.paddingRight(7)
.paddingInner(3) // Padding between each rectangle
//.paddingOuter(6)
//.padding(20)
(root)
// prepare a color scale
var color = d3.scaleOrdinal()
.domain(["source1", "source2", "source3"])
.range([ "#402D54", "#D18975", "#8FD175"])
// And a opacity scale
var opacity = d3.scaleLinear()
.domain([10, 30])
.range([.5,1])
// use this information to add rectangles:
svg2
.selectAll("rect")
.data(root.leaves())
.enter()
.append("rect")
.attr('x', function (d) { return d.x0; })
.attr('y', function (d) { return d.y0; })
.attr('width', function (d) { return d.x1 - d.x0; })
.attr('height', function (d) { return d.y1 - d.y0; })
.style("stroke", "black")
.style("fill", function(d){ return color(d.parent.data.name)} )
.style("opacity", function(d){ return opacity(d.data.value)})
// and to add the text labels
svg2
.selectAll("text")
.data(root.leaves())
.enter()
.append("text")
.attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right)
.attr("y", function(d){ return d.y0+20}) // +20 to adjust position (lower)
.text(function(d){ return d.data.name.replace('mister_','') })
.attr("font-size", "19px")
.attr("fill", "white")
// and to add the text labels
svg2
.selectAll("vals")
.data(root.leaves())
.enter()
.append("text")
.attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right)
.attr("y", function(d){ return d.y0+35}) // +20 to adjust position (lower)
.text(function(d){ return d.data.value })
.attr("font-size", "11px")
.attr("fill", "white")
// Add title for the 3 groups
svg2
.selectAll("titles")
.data(root.descendants().filter(function(d){return d.depth==1}))
.enter()
.append("text")
.attr("x", function(d){ return d.x0})
.attr("y", function(d){ return d.y0+21})
.text(function(d){ return d.data.name })
.attr("font-size", "19px")
.attr("fill", function(d){ return color(d.data.name)} )
// Add title for the 3 groups
svg2
.append("text")
.attr("x", 0)
.attr("y", 14) // +20 to adjust position (lower)
.text("Three group sources")
.attr("font-size", "19px")
.attr("fill", "grey" )
})
.dataviz {
display: inline-block;
}
<script src="https://d3js.org/d3.v4.js"></script>
<div>
<div class="dataviz" id="my_dataviz1"></div>
<div class="dataviz" id="my_dataviz2"></div>
</div>

D3.js how to add grid boxes for value ranges

I'm trying to find a way to add grid boxes to my D3.js scatterplot. The boxes should have a certain color depending on in which value range they reside. For example the box that is between x value 0-20 and y value 0-20 should be green.
What I have now:
What I want - Illustration:
I know that I could add a background image for the svg, but that doesn't seem to be a viable solution.
My code so far:
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 1200 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// setup x
var xValue = function(d) { return d.Impact;}, // data -> value
xScale = d3.scale.linear().range([0, width]), // value -> display
xMap = function(d) { return xScale(xValue(d));}, // data -> display
xAxis = d3.svg.axis().scale(xScale).orient("bottom");
// setup y
var yValue = function(d) { return d.Likelihood;}, // data -> value
yScale = d3.scale.linear().range([height, 0]), // value -> display
yMap = function(d) { return yScale(yValue(d));}, // data -> display
yAxis = d3.svg.axis().scale(yScale).orient("left");
// setup fill color
var cValue = function(d) { return d.Conf;},
color = d3.scale.category20();
// add the graph canvas to the body of the webpage
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right + 400)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// add the tooltip area to the webpage
var tooltip = d3.select("#chart").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// change string (from CSV) into number format
data.forEach(function(d) {
d,Impact = +d.Impact;
d.Likelihood = +d.Likelihood;
});
// don't want dots overlapping axis, so add in buffer to data domain
xScale.domain([d3.min(data, xValue)-1, d3.max(data, xValue)+1]);
yScale.domain([d3.min(data, yValue)-1, d3.max(data, yValue)+1]);
// scales w/o extra padding
xScale.domain([d3.min(data, xValue), d3.max(data, xValue)]);
yScale.domain([d3.min(data, yValue), d3.max(data, yValue)]);
// x-axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.attr("class", "grid")
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("Likelihood");
// y-axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.attr("class", "grid")
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Impact");
// draw dots
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 5.5)
.attr("cx", xMap)
.attr("cy", yMap)
.style("fill", function(d) { return color(d.CategoryMain);})
.on("mouseover", function(d) {
tooltip.transition()
.duration(200)
.style("opacity", .9);
tooltip.html(d.CategoryMain + "<br/> " + d.CategorySub1 + "<br/>(" + xValue(d)
+ ", " + yValue(d) + ")")
.style("left", (d3.event.pageX + 10) + "px")
.style("top", (d3.event.pageY - 10) + "px");
})
.on("mouseout", function(d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
// draw legend
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(160," + (i+7) * 20 + ")"; });
// draw legend colored rectangles
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
// draw legend text
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d;})
})
Any suggestions how this could be done?

how to plot data from JSON object on .svg file using D3.js

Image is appending as a background which is not clear.
Able to plot data on svg element which is created in this code.
But want to plot json data on image/.svg file with the following..
Will appreciate if any references...
$(function(){
makePlot();
// $('#zoomReset').on('click',function(e){
// e.preventDefault();
// //$('#chart').empty();
// console.log("sadf");
// makePlot();
// });
});
var makePlot = function() {
d3.json("scatter-data-2010.json", function(dataset) {
//Width and height
var margin = {top: 80, right: 10, bottom: 60, left: 80},
width = 600 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var centered = undefined;
//Create SVG element
tooltip = d3.select("body").append("div")
.attr("class", "plan_tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("");
var svg = d3.select("#vis")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
/// Set Scales and Distortions
var xScale = d3.scale.linear()
.domain([d3.min(dataset, function(d) { return d['n_workers_change']; }), d3.max(dataset, function(d) { return d['n_workers_change']; })])
.range([0, width]);
var yScale = d3.scale.linear()
.domain([d3.min(dataset, function(d) { return d['earnings_change']; }), d3.max(dataset, function(d) { return d['earnings_change']; })])
.range([height,0]);
var color_scale = d3.scale.category20();
//Add 2 more colors to category 20 because there are 22 parent industry categories
var color_scale_range = color_scale.range();
color_scale_range.push("#e6550d","#6baed6")
radiusScale = d3.scale.sqrt()
.domain([d3.min(dataset, function(d) { return d['n_workers_y']; }), d3.max(dataset, function(d) { return d['n_workers_y']; }) ])
.range([3, 15]);
svg.append("defs")
.append("pattern")
.attr("id", "background")
.attr("width", width)
.attr("height", height)
.append("image")
.attr("xlink:href", "http://www.e-pint.com/epint.jpg")
.attr("width", width)
.attr("height", height);
var rect = svg.append("rect")
.attr("class", "background")
.attr("pointer-events", "all")
//.attr("fill","none")
.attr("fill","url(#background)")
.attr("width", width)
.attr("height", height)
.call(d3.behavior.zoom().x(xScale).y(yScale).on("zoom", redraw));
// Tooltips for Dots
set_tooltip_label = function (d) {
var company_name;
tooltip.html(d.category + "<br><strong>N Workers in 2010 (thousands)</strong>: " + d['n_workers_y'] + "<br><strong>Med. Wkly Earnings in 2010 ($)</strong>: " + d.earnings_y + "<br><strong> Category</strong>: " + d.parent_name );
if (!(event === undefined)) {
tooltip.style("top", (event.pageY - 10) + "px").style("left", (event.pageX + 10) + "px")
}
};
var circles = svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("clip-path", "url(#clip)")
// Set cx, cy in the redraw function
.attr("r", function(d) {
return radiusScale(d['n_workers_y']);
})
.attr("fill", function(d) {
return color_scale(d.parent_id)
})
.on("mouseover", function () {
return tooltip.style("visibility", "visible")
}).on("mousemove", function (d) {
set_tooltip_label(d);
}).on("mouseout", function () {
tooltip.style("visibility", "hidden");
});
// Define X axis
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(5)
.tickSize(-height)
.tickFormat(d3.format("s"));
// Define Y axis
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(10)
.tickFormat(function(d) { return d + " %"; })
.tickSize(-width);
// Create X axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height) + ")")
.call(xAxis);
// Create Y axis
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + 0 + ",0)")
.call(yAxis);
// Add Label to X Axis
svg.append("text")
.attr("class", "x label")
.attr("text-anchor", "middle")
.attr("x", width - width/2)
.attr("y", height + margin.bottom/2)
.text("Percent Change in Number of Workers in Industry");
// Add label to Y Axis
svg.append("text")
.attr("class", "y label")
.attr("text-anchor", "middle")
.attr("y", -margin.left + 5)
.attr("x", 0 - (height/2))
.attr("dy", "1em")
.attr("transform", "rotate(-90)")
.text("Percent Change in Inflation Adjusted Median Weekly Earnings");
// Add title
svg.append("text")
.attr("class", " title")
.attr("text-anchor","middle")
.attr("x", width/2)
.attr("y", -margin.top/2)
.text("Changes in Employment and Salary by Industry, 2003 - 2010");
// Add subtitle
svg.append("text")
.attr("class", "subtitle")
.attr("text-anchor","middle")
.attr("x", width/2)
.attr("y", -margin.top/2 + 15)
.text("Scroll and drag to zoom/pan, hover for details.");
var objects = svg.append("svg")
.attr("class", "objects")
.attr("width", width)
.attr("height", height);
//Create main 0,0 axis lines:
hAxisLine = objects.append("svg:line")
.attr("class", "axisLine hAxisLine");
vAxisLine = objects.append("svg:line")
.attr("class", "axisLine vAxisLine");
// Zoom/pan behavior:
function redraw(duration) {
var duration = typeof duration !== 'undefined' ? duration : 0;
if (d3.event){
//console.log("In the zoom function now");
//console.log(d3.event.scale);
//console.log(d3.event.translate);
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
}
hAxisLine.transition().duration(duration)
.attr("x1",0)
.attr("y1",0)
.attr("x2",width)
.attr("y2",0)
.attr("transform", "translate(0," + (yScale(0)) + ")");
vAxisLine.transition().duration(duration)
.attr("x1",xScale(0))
.attr("y1",yScale(height))
.attr("x2",xScale(0))
.attr("y2",yScale(-height));
circles.transition().duration(duration)
.attr("cx", function(d) {
return xScale(d['n_workers_change']);
})
.attr("cy", function(d) {
return yScale(d['earnings_change']);
})
}; // <-------- End of zoom function
redraw(0); // call zoom to place elements
}); // end of json loading section
};
You need to define the background image as a pattern and then fill the rect with that pattern:
svg.append("defs")
.append("pattern")
.attr("id", "background")
.attr("width", width)
.attr("height", height)
.append("image")
.attr("xlink:href", "http://www.e-pint.com/epint.jpg")
.attr("width", width)
.attr("height", height);
svg.append("rect")
.attr("fill", "url(#background)");

Categories

Resources