Counter10000
Counter10000

Reputation: 524

D3 Data Loading For A Choropleth Graph or Heat Map

I am trying to use this as an example of US Choropleth graph (AKA Heat Map) for my own csv data. I copied the original code, and only changed the data source, then it is not working. So I figure that my data loading is wrong. But I can not figure out how to fix it. Could you help? Any help is appreciated.

Please see my code below or use this JSFiddle link. Well, I don't know how to load my csv data in JSFiddle, so it is not supposed to work there anyway. I will share my csv file below.

Edit: One leeway I can think of is to add the data in JavaScript, which is not efficient, but works. I look into the original data format, and mimic it. I attach this "solution" at the bottom shown as Code 2.

Code:

<!DOCTYPE html>
<meta charset="utf-8">
<style>
    .state{
        fill: none;
        stroke: #a9a9a9;
        stroke-width: 1;
    }
    .state:hover{
        fill-opacity:0.5;
    }
    #tooltip {   
        position: absolute;           
        text-align: center;
        padding: 20px;             
        margin: 10px;
        font: 12px sans-serif;        
        background: lightsteelblue;   
        border: 1px;      
        border-radius: 2px;           
        pointer-events: none;         
    }
    #tooltip h4{
        margin:0;
        font-size:14px;
    }
    #tooltip{
        background:rgba(0,0,0,0.9);
        border:1px solid grey;
        border-radius:5px;
        font-size:12px;
        width:auto;
        padding:4px;
        color:white;
        opacity:0;
    }
    #tooltip table{
        table-layout:fixed;
    }
    #tooltip tr td{
        padding:0;
        margin:0;
    }
    #tooltip tr td:nth-child(1){
        width:50px;
    }
    #tooltip tr td:nth-child(2){
        text-align:center;
    }
</style>
<body>
<div id="tooltip"></div> <!-- div to hold tooltip. -->
<svg width="960" height="600" id="statesvg"></svg> <!-- svg to hold the map. -->
<script src="http://bl.ocks.org/NPashaP/raw/a74faf20b492ad377312/uStates.js"></script>  <!-- creates uStates. -->
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>

    function tooltipHtml(n, d){ /* function to create html content string in tooltip div. */
        return "<h4>"+n+"</h4><table>"+
            "<tr><td>Net</td><td>"+(d.Net)+"</td></tr>"+
            "<tr><td>In</td><td>"+(d.In)+"</td></tr>"+
            "<tr><td>Out</td><td>"+(d.Out)+"</td></tr>"+
            "</table>";
    }

    var sampleData ={}; /* Sample random data. */   
    <!-- ["HI", "AK", "FL", "SC", "GA", "AL", "NC", "TN", "RI", "CT", "MA", "ME", "NH", "VT", "NY", "NJ", "PA", "DE", "MD",  -->
    <!-- "WV", "KY", "OH", "MI", "WY", "MT", "ID", "WA", "DC", "TX", "CA", "AZ", "NV", "UT", "CO", "NM", "OR", "ND", "SD",  -->
    <!-- "NE", "IA", "MS", "IN", "IL", "MN", "WI", "MO", "AR", "OK", "KS", "LS", "VA"] -->
    <!-- .forEach(function(d){  -->
            <!-- var Net=Math.round(100*Math.random()),  -->
            <!-- In=Math.round(100*Math.random()),  -->
            <!-- Out=Math.round(100*Math.random()); -->
    <!-- sampleData[d]={ -->
            <!-- Net:d3.min([Net,In,Out]),  -->
            <!-- In:d3.max([Net,In,Out]),  -->
            <!-- Out:Math.round((Net+In+Out)/3),  -->
            <!-- color:d3.interpolate("#ffffcc", "#800026")(Net/100)};  -->
        <!-- }); -->
    sampleData = d3.csv("Test.csv", function(data){
                         data.forEach(function(d) {
                         State: d.State,
                         Net: +d.Net,
                         In: +d.In,
                         Out: +d.Out,
                         color: d3.interpolate("#ffffcc", "#800026")(Net/100)};
                     });
        console.log(data[0]);
    });

    /* draw states on id #statesvg */   
    uStates.draw("#statesvg", sampleData, tooltipHtml);

    d3.select(self.frameElement).style("height", "600px"); 
</script>

</body>

CSV file:

State,Net,In,Out
"""AK""",12215,53952,41737
"""AL""",16443,35063,18620
"""AR""",62902,75160,12258
"""AZ""",13931,77911,63980
"""CA""",94043,98042,3999
"""CO""",59769,93780,34011
"""CT""",-14958,24957,39915
"""DC""",29903,86390,56487
"""DE""",-65779,16257,82036
"""FL""",-51446,34313,85759
"""GA""",29685,37768,8083
"""IA""",-42416,56750,99166
"""ID""",-32028,41536,73564
"""IL""",-86579,8818,95397
"""IN""",-38841,9576,48417
"""KS""",-20601,36955,57556
"""KY""",-1593,37728,39321
"""LS""",-2574,34066,36640
"""MA""",-47842,34838,82680
"""MD""",-46721,9290,56011
"""ME""",-65431,21563,86994
"""MI""",-6542,53094,59636
"""MN""",-6034,76869,82903
"""MO""",-73558,20641,94199
"""MS""",24958,87012,62054
"""MT""",28657,75139,46482
"""NC""",56536,79399,22863
"""ND""",27423,61184,33761
"""NE""",-32070,22564,54634
"""NH""",-60000,21133,81133
"""NJ""",-45478,45954,91432
"""NM""",54333,78167,23834
"""NV""",26792,55773,28981
"""NY""",-18735,35722,54457
"""OH""",-76722,10843,87565
"""OK""",23052,65474,42422
"""OR""",-31368,67948,99316
"""PA""",8303,70657,62354
"""RI""",4516,26086,21570
"""SC""",-57549,36354,93903
"""SD""",11788,46551,34763
"""TN""",38178,88302,50124
"""TX""",-8142,47607,55749
"""UT""",-59301,20661,79962
"""VA""",-44967,27957,72924
"""VT""",95214,98784,3570
"""WA""",32652,33543,891
"""WI""",10484,23835,13351
"""WV""",12462,31829,19367
"""WY""",-20751,49812,70563
"""HI""",-54981,7388,62369

Code 2:

<!DOCTYPE html>
<meta charset="utf-8">
<style>
    .state{
        fill: none;
        stroke: #a9a9a9;
        stroke-width: 1;
    }
    .state:hover{
        fill-opacity:0.5;
    }
    #tooltip {   
        position: absolute;           
        text-align: center;
        padding: 20px;             
        margin: 10px;
        font: 12px sans-serif;        
        background: lightsteelblue;   
        border: 1px;      
        border-radius: 2px;           
        pointer-events: none;         
    }
    #tooltip h4{
        margin:0;
        font-size:14px;
    }
    #tooltip{
        background:rgba(0,0,0,0.9);
        border:1px solid grey;
        border-radius:5px;
        font-size:12px;
        width:auto;
        padding:4px;
        color:white;
        opacity:0;
    }
    #tooltip table{
        table-layout:fixed;
    }
    #tooltip tr td{
        padding:0;
        margin:0;
    }
    #tooltip tr td:nth-child(1){
        width:50px;
    }
    #tooltip tr td:nth-child(2){
        text-align:center;
    }
</style>
<body>
<div id="tooltip"></div> <!-- div to hold tooltip. -->
<svg width="960" height="600" id="statesvg"></svg> <!-- svg to hold the map. -->
<script src="http://bl.ocks.org/NPashaP/raw/a74faf20b492ad377312/uStates.js"></script>  <!-- creates uStates. -->
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>

    function tooltipHtml(n, d){ /* function to create html content string in tooltip div. */
        return "<h4>"+n+"</h4><table>"+
            "<tr><td>Net</td><td>"+(d.Net)+"</td></tr>"+
            "<tr><td>In</td><td>"+(d.In)+"</td></tr>"+
            "<tr><td>Out</td><td>"+(d.Out)+"</td></tr>"+
            "</table>";
    }

    var sampleData ={}; /* Sample random data. */   
    <!-- 1. Original Solution -->
    <!-- ["HI", "AK", "FL", "SC", "GA", "AL", "NC", "TN", "RI", "CT", "MA", "ME", "NH", "VT", "NY", "NJ", "PA", "DE", "MD",  -->
    <!-- "WV", "KY", "OH", "MI", "WY", "MT", "ID", "WA", "DC", "TX", "CA", "AZ", "NV", "UT", "CO", "NM", "OR", "ND", "SD",  -->
    <!-- "NE", "IA", "MS", "IN", "IL", "MN", "WI", "MO", "AR", "OK", "KS", "LS", "VA"] -->
    <!-- .forEach(function(d){  -->
            <!-- var Net=Math.round(100*Math.random()),  -->
            <!-- In=Math.round(100*Math.random()),  -->
            <!-- Out=Math.round(100*Math.random()); -->
    <!-- sampleData[d]={ -->
            <!-- Net:d3.min([Net,In,Out]),  -->
            <!-- In:d3.max([Net,In,Out]),  -->
            <!-- Out:Math.round((Net+In+Out)/3),  -->
            <!-- color:d3.interpolate("#ffff32", "#3232ff")(Net/100)};  -->
        <!-- }); -->

    <!-- 2. Load CSV -->
    <!-- sampleData = d3.csv("Test.csv", function(data){ -->
                         <!-- data.forEach(function(d) { -->
                         <!-- d.Net = +d.Net; -->
                         <!-- d.In = +d.In; -->
                         <!-- d.Out = +d.Out; -->
                         <!-- color = d3.interpolate("#ffff32", "#3232ff")(Net/100)}; -->
                     <!-- }); -->
        <!-- console.log(data[0]); -->
    <!-- }); -->

    <!-- 3. Load Data -->
    sampleData = {
"AK":{"Net":13673,"In":72772,"Out":59099,"color":d3.interpolate("#ffff32", "#3232ff")(0.568365)},
"AL":{"Net":46349,"In":59672,"Out":13323,"color":d3.interpolate("#ffff32", "#3232ff")(0.731745)},
"AR":{"Net":-31164,"In":38140,"Out":69304,"color":d3.interpolate("#ffff32", "#3232ff")(0.34418)},
"AZ":{"Net":-27113,"In":57824,"Out":84937,"color":d3.interpolate("#ffff32", "#3232ff")(0.364435)},
"CA":{"Net":-42460,"In":12772,"Out":55232,"color":d3.interpolate("#ffff32", "#3232ff")(0.2877)},
"CO":{"Net":9039,"In":9163,"Out":124,"color":d3.interpolate("#ffff32", "#3232ff")(0.545195)},
"CT":{"Net":-8192,"In":60579,"Out":68771,"color":d3.interpolate("#ffff32", "#3232ff")(0.45904)},
"DC":{"Net":15000,"In":45262,"Out":30262,"color":d3.interpolate("#ffff32", "#3232ff")(0.575)},
"DE":{"Net":39455,"In":93112,"Out":53657,"color":d3.interpolate("#ffff32", "#3232ff")(0.697275)},
"FL":{"Net":6592,"In":44256,"Out":37664,"color":d3.interpolate("#ffff32", "#3232ff")(0.53296)},
"GA":{"Net":19317,"In":25254,"Out":5937,"color":d3.interpolate("#ffff32", "#3232ff")(0.596585)},
"IA":{"Net":119,"In":46902,"Out":46783,"color":d3.interpolate("#ffff32", "#3232ff")(0.500595)},
"ID":{"Net":21304,"In":94961,"Out":73657,"color":d3.interpolate("#ffff32", "#3232ff")(0.60652)},
"IL":{"Net":6726,"In":96451,"Out":89725,"color":d3.interpolate("#ffff32", "#3232ff")(0.53363)},
"IN":{"Net":66445,"In":71900,"Out":5455,"color":d3.interpolate("#ffff32", "#3232ff")(0.832225)},
"KS":{"Net":43263,"In":63770,"Out":20507,"color":d3.interpolate("#ffff32", "#3232ff")(0.716315)},
"KY":{"Net":28409,"In":39524,"Out":11115,"color":d3.interpolate("#ffff32", "#3232ff")(0.642045)},
"LS":{"Net":-32758,"In":36865,"Out":69623,"color":d3.interpolate("#ffff32", "#3232ff")(0.33621)},
"MA":{"Net":-77135,"In":20768,"Out":97903,"color":d3.interpolate("#ffff32", "#3232ff")(0.114325)},
"MD":{"Net":33582,"In":52556,"Out":18974,"color":d3.interpolate("#ffff32", "#3232ff")(0.66791)},
"ME":{"Net":-33661,"In":63381,"Out":97042,"color":d3.interpolate("#ffff32", "#3232ff")(0.331695)},
"MI":{"Net":25521,"In":46300,"Out":20779,"color":d3.interpolate("#ffff32", "#3232ff")(0.627605)},
"MN":{"Net":-67244,"In":23014,"Out":90258,"color":d3.interpolate("#ffff32", "#3232ff")(0.16378)},
"MO":{"Net":-31720,"In":28241,"Out":59961,"color":d3.interpolate("#ffff32", "#3232ff")(0.3414)},
"MS":{"Net":45311,"In":61848,"Out":16537,"color":d3.interpolate("#ffff32", "#3232ff")(0.726555)},
"MT":{"Net":-6116,"In":33017,"Out":39133,"color":d3.interpolate("#ffff32", "#3232ff")(0.46942)},
"NC":{"Net":-1072,"In":32219,"Out":33291,"color":d3.interpolate("#ffff32", "#3232ff")(0.49464)},
"ND":{"Net":30661,"In":42404,"Out":11743,"color":d3.interpolate("#ffff32", "#3232ff")(0.653305)},
"NE":{"Net":68355,"In":99399,"Out":31044,"color":d3.interpolate("#ffff32", "#3232ff")(0.841775)},
"NH":{"Net":18610,"In":61242,"Out":42632,"color":d3.interpolate("#ffff32", "#3232ff")(0.59305)},
"NJ":{"Net":38709,"In":61706,"Out":22997,"color":d3.interpolate("#ffff32", "#3232ff")(0.693545)},
"NM":{"Net":15182,"In":46812,"Out":31630,"color":d3.interpolate("#ffff32", "#3232ff")(0.57591)},
"NV":{"Net":-10893,"In":86934,"Out":97827,"color":d3.interpolate("#ffff32", "#3232ff")(0.445535)},
"NY":{"Net":-54467,"In":40371,"Out":94838,"color":d3.interpolate("#ffff32", "#3232ff")(0.227665)},
"OH":{"Net":21695,"In":26311,"Out":4616,"color":d3.interpolate("#ffff32", "#3232ff")(0.608475)},
"OK":{"Net":-50523,"In":30579,"Out":81102,"color":d3.interpolate("#ffff32", "#3232ff")(0.247385)},
"OR":{"Net":-51906,"In":37801,"Out":89707,"color":d3.interpolate("#ffff32", "#3232ff")(0.24047)},
"PA":{"Net":-89879,"In":2858,"Out":92737,"color":d3.interpolate("#ffff32", "#3232ff")(0.050605)},
"RI":{"Net":-3146,"In":6730,"Out":9876,"color":d3.interpolate("#ffff32", "#3232ff")(0.48427)},
"SC":{"Net":22085,"In":54977,"Out":32892,"color":d3.interpolate("#ffff32", "#3232ff")(0.610425)},
"SD":{"Net":28055,"In":58411,"Out":30356,"color":d3.interpolate("#ffff32", "#3232ff")(0.640275)},
"TN":{"Net":-75690,"In":4153,"Out":79843,"color":d3.interpolate("#ffff32", "#3232ff")(0.12155)},
"TX":{"Net":-55786,"In":27575,"Out":83361,"color":d3.interpolate("#ffff32", "#3232ff")(0.22107)},
"UT":{"Net":-63853,"In":76,"Out":63929,"color":d3.interpolate("#ffff32", "#3232ff")(0.180735)},
"VA":{"Net":44965,"In":69720,"Out":24755,"color":d3.interpolate("#ffff32", "#3232ff")(0.724825)},
"VT":{"Net":-18735,"In":39534,"Out":58269,"color":d3.interpolate("#ffff32", "#3232ff")(0.406325)},
"WA":{"Net":-8462,"In":48597,"Out":57059,"color":d3.interpolate("#ffff32", "#3232ff")(0.45769)},
"WI":{"Net":-53972,"In":28418,"Out":82390,"color":d3.interpolate("#ffff32", "#3232ff")(0.23014)},
"WV":{"Net":-2571,"In":60715,"Out":63286,"color":d3.interpolate("#ffff32", "#3232ff")(0.487145)},
"WY":{"Net":-16086,"In":52706,"Out":68792,"color":d3.interpolate("#ffff32", "#3232ff")(0.41957)},
"HI":{"Net":1418,"In":15119,"Out":13701,"color":d3.interpolate("#ffff32", "#3232ff")(0.50709)}
};


    /* draw states on id #statesvg */   
    uStates.draw("#statesvg", sampleData, tooltipHtml);

    d3.select(self.frameElement).style("height", "600px"); 
</script>

</body>

Upvotes: 1

Views: 343

Answers (1)

Andrew Reid
Andrew Reid

Reputation: 38231

I'm not sure that you can use d3.json in the manner you are. I haven't seen it before at least. Also, your forEach code won't give you the result you are looking for. Your code as is should produce an error like this:

SyntaxError: missing ; before statement[Learn More]  map.html:71:28

When you are coloring the paths you need to have a property that has the state abbreviation (which holds an object of properties such as color). You need to make a dictionary. You could use:

var sampleData ={};     
d3.csv("Test.csv", function(data){
  data.forEach(function(d) {
    sampleData[d.State] = { 
      Net : +d.Net, 
      In : +d.In, 
      Out : +d.Out, 
      color : d3.interpolate("#ffffcc", "#800026")(d.Net/100) 
    };
  });
});

Loggin sampleData will give you something like:

Object { AK: Object, AL: Object, AR: Object, AZ: Object, CA: Object, CO: Object, CT: Object, DC: Object, DE: Object, FL: Object, 41 more… }

But, sampleData will only be defined in the callback function of d3.json - as d3.json is asynchronous. Therefore you'll need to call the drawing function within it.

So your code should look like:

var sampleData ={};     
d3.csv("Test.csv", function(data){
  data.forEach(function(d) {
    sampleData[d.State] = { 
      Net : +d.Net, 
      In : +d.In, 
      Out : +d.Out, 
      color : d3.interpolate("#ffffcc", "#800026")(d.Net/100) 
    };
  });
  uStates.draw("#statesvg", sampleData, tooltipHtml);
});

This gives me this:

enter image description here

The data is pairing properly (you can see the values in the mouseover). However, while not in your question, your colors are not done properly, they are all #ffffff or #000000. Try using a scale:

var sampleData ={};     
d3.csv("Test.csv", function(data){
  var color = d3.scale.linear()
    .range(["steelblue","orange"])
    .domain([d3.min(data, function(d) { return d.Net/100; }), d3.max(data, function(d) { return d.Net/100; }) ])
  data.forEach(function(d) {
    sampleData[d.State] = { 
      Net : +d.Net, 
      In : +d.In, 
      Out : +d.Out, 
      color : color(d.Net/100);
    };
  });
});

Which gives me:

enter image description here

Here is a demonstration of your code in action with the above tweaks. Oh, and I also removed the quotations from the csv file, no need to include them.

Upvotes: 1

Related Questions