Created
May 10, 2016 19:01
-
-
Save nharrisanalyst/3212bfbdd750d3a17930988c7781f710 to your computer and use it in GitHub Desktop.
Nathan Harris realtime dataviz using saccounty open data api
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> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=UTF8"> | |
<title>A real time data visualization</title> | |
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/1.10.0/d3-legend.js"></script> | |
<script src="https://d3js.org/d3-queue.v2.min.js"></script> | |
<script> | |
q=d3_queue.queue(); | |
</script> | |
<style> | |
.title{ | |
} | |
#g0 { fill: #eafeea; } | |
#g1 { fill: #d5fdd5; } | |
#g2 { fill: #c1fcc1; } | |
#g3 { fill: #acfbac; } | |
#g4 { fill: #88e188; } | |
#g5 { fill: #6aaf6a; } | |
#g6 { fill: #4c7d4c; } | |
#g7 { fill: #2d4b2d; } | |
.g0 { fill: #eafeea; } | |
.g1 { fill: #d5fdd5; } | |
.g2 { fill: #c1fcc1; } | |
.g3 { fill: #acfbac; } | |
.g4 { fill: #88e188; } | |
.g5 { fill: #6aaf6a; } | |
.g6 { fill: #4c7d4c; } | |
.g7 { fill: #2d4b2d; } | |
.zipcode{stroke:black;} | |
</style> | |
</head> | |
<body> | |
<h1 class="title"> Sacramento County 311 Calls by Zipcode Up to Date API call</h1> | |
<p>Sacramento County 311 handles all County municipal service requests that are not police and fire related. | |
this map and bar chart makes up to date request from http://data.saccounty.net/home api | |
the data automatically updates when the api is updated. If the website is left open the api is called every 15 min<p> | |
<script> | |
//??twitter real time api search | |
//https://api.twitter.com/1.1/search/tweets.json?q=donald%20trump&src=typd | |
// api key http://www.divvybikes.com/stations/json | |
(function(){ | |
var rectData=[] | |
var scaleX | |
var data; | |
var dataGeo | |
var dataZipcode={}; | |
var dataCalls={}; | |
var h = 600; | |
var w = 550; | |
var width=400; | |
var svg =d3.select("body").append("svg") | |
.attr("width",w) | |
.attr("height",h) | |
.attr("id","svgone"); | |
var projection= d3.geo.albers() | |
.scale(45000) | |
.rotate([120.5,.25,0]); | |
var path = d3.geo.path() | |
.projection(projection); | |
var quantize; | |
var newData; | |
var check; | |
var newDict={}; | |
var mapDict={}; | |
//ordinal scale | |
var ordinal=d3.scale.ordinal().domain(["#g0","#g1","#g2","#g3","#g4","#g5","#g6","#g7"]) | |
.range(["#eafeea","#d5fdd5","#c1fcc1","#acfbac","#88e188","#6aaf6a","#4c7d4c","#2d4b2d"]) | |
//mouseover mouseout | |
var selecetion; | |
var mouseover= function(d){ | |
var z = this.getAttribute('class') | |
console.log(z) | |
if(z.slice(0,1)=="y"){ | |
var z = this.getAttribute('class'); | |
var y = z.slice(1,6); | |
d3.select("." + this.getAttribute('class')) | |
.style("fill","orange") | |
d3.select('.z'+y) | |
.style("fill","orange") | |
d3.select('#svgone') | |
.append("text") | |
.attr("class","text") | |
.attr({ | |
x:5, | |
y:250, | |
"font-size": "12px", | |
"font-family":"Sans-Serif" | |
}) | |
.text("Name: "+d.properties.PO_NAME) | |
d3.select('#svgone') | |
.append("text") | |
.attr("class","text") | |
.attr({ | |
x:5, | |
y:260, | |
"font-size": "12px", | |
"font-family":"Sans-Serif" | |
}) | |
.text("Zipcode: " +d.properties.ZIP5+ ", Calls: " +newDict[d.properties.ZIP5])} | |
else{ | |
var z = this.getAttribute('class'); | |
var y = z.slice(1,6); | |
d3.select("." + this.getAttribute('class')) | |
.style("fill","orange"); | |
d3.select('.y'+y) | |
.style("fill","orange") | |
d3.select('#svgone') | |
.append("text") | |
.attr("class","text") | |
.attr({ | |
x:5, | |
y:250, | |
"font-size": "12px", | |
"font-family":"Sans-Serif" | |
}) | |
.text("Name: "+mapDict[d.zipcode].name) | |
d3.select('#svgone') | |
.append("text") | |
.attr("class","text") | |
.attr({ | |
x:5, | |
y:260, | |
"font-size": "12px", | |
"font-family":"Sans-Serif" | |
}) | |
.text("Zipcode: " +mapDict[d.zipcode].zipcode+ ", Calls: " +mapDict[d.zipcode].calls)} | |
}; | |
var mouseout= function(d){ | |
var z = this.getAttribute('class') | |
console.log(z.slice(0,1)=="y") | |
if(z.slice(0,1)=="y"){ | |
var z = this.getAttribute('class'); | |
var y = z.slice(1,6); | |
var color=ordinal('#'+quantize(newDict[d.properties.ZIP5])) | |
console.log(color) | |
d3.select("." + this.getAttribute('class')) | |
.style("fill",ordinal('#'+quantize(newDict[d.properties.ZIP5]))) | |
d3.select('.z'+y) | |
.style("fill",ordinal('#'+quantize(newDict[d.properties.ZIP5]))) | |
d3.selectAll(".text").remove() | |
}else{ | |
console.log(d.calls) | |
console.log('#'+quantize(d.calls)) | |
console.log(ordinal(quantize(d.calls))) | |
var z = this.getAttribute('class'); | |
var y = z.slice(1,6); | |
d3.select("." + this.getAttribute('class')) | |
.style("fill",ordinal('#'+quantize(d.calls))); | |
d3.select('.y'+y) | |
.style("fill",ordinal('#'+quantize(d.calls)))} | |
d3.selectAll('.text').remove(); | |
}; | |
//defer double request | |
q.defer(d3.json,"http://saccounty.cloudapi.junar.com/api/v2/datastreams/311-CASES-BY-ZIPCO-SUMMA/data.json/?auth_key=77bf2351cdb42d68f577b6c54041550cf708b773") | |
.defer(d3.json,"http://localhost:8000/Desktop/Web%20Dev%20professional/real_time/data/saczipgeo.json") | |
.awaitAll(ready) | |
function ready(error,first){ | |
if(error){alert("You had an error retrieving data");} | |
//preparing data and everything for first json file | |
data=first; | |
data=data[0]; | |
data.result.fArray.forEach(function(value,i){ | |
if(i%2==0){ | |
dataZipcode[i]=data.result.fArray[i].fStr | |
} | |
if(i%2!=0){ | |
dataCalls[i]=data.result.fArray[i].fStr | |
} | |
}); | |
data=[]; | |
for ( i=0;i<=108;i=i+2){ | |
if(i==0){ | |
data[i]={"zipcode":dataZipcode[i],"calls":dataCalls[i+1]}; | |
} | |
data[i/2]={"zipcode":dataZipcode[i],"calls":dataCalls[i+1]}; | |
}; | |
//scale for data colors | |
var maxD=d3.max(data.slice(1,data.length-1),function(d){return parseInt(d.calls)}); | |
console.log(maxD); | |
var minD=d3.min(data.slice(1,data.length-1),function(d){return d.calls}); | |
quantize= d3.scale.quantize() | |
.domain([0,maxD]) | |
.range(d3.range(8).map(function(i) { return "g"+i; })); | |
data.forEach(function(d){return newDict[d.zipcode]= +d.calls;}); | |
//preparing for the second json | |
dataGeo=first[1]; | |
dataGeo=dataGeo.features | |
//checking for zipcodes that had zero calls(will be undefined in the dataMap object | |
for(i=0;i<dataGeo.length;i++){ | |
if (newDict[dataGeo[i].properties.ZIP5] === undefined){ | |
newDict[dataGeo[i].properties.ZIP5]=0; | |
}; | |
}; | |
svg.selectAll("zipcode") | |
.data(dataGeo) | |
.enter().append("path") | |
.attr("d", path) | |
.attr("class",function(d){return 'y'+ d.properties.ZIP5}) | |
.attr("id",function(d){return quantize(newDict[d.properties.ZIP5])}) | |
.attr("stroke","black") | |
.on("mouseover",mouseover) | |
.on("mouseout",mouseout) | |
var svg2=d3.select("body") | |
.append("svg") | |
.attr({ | |
width: width, | |
height:h, | |
id:"svgtwo" | |
}); | |
scaleX = d3.scale.linear() | |
.domain([0,maxD]) | |
.range([0,width]); | |
for(i=0;i<dataGeo.length;i++){ | |
rectData[i] = {"zipcode":dataGeo[i].properties.ZIP5,"calls":newDict[dataGeo[i].properties.ZIP5]} | |
}; | |
rectData.sort(function(a, b){ | |
return b.calls-a.calls; | |
}) | |
var barPadding=1; | |
svg2.selectAll("rect") | |
.data(rectData) | |
.enter() | |
.sort(function(a, b) { | |
return d3.ascending(a, b); | |
}) | |
.append("rect") | |
.attr("width",function(d){return scaleX(d.calls)}) | |
.attr("height", function(d,i){return (h/rectData.length)-barPadding;}) | |
.attr("y",function(d,i){return (h/rectData.length)*i;}) | |
.attr("id",function(d){return quantize(d.calls)}) | |
.attr("class",function(d){return 'z'+d.zipcode;}) | |
.on("mouseover",mouseover) | |
.on("mouseout",mouseout); | |
for(i=0;i<dataGeo.length;i++){ | |
mapDict[dataGeo[i].properties.ZIP5]={'name':dataGeo[i].properties.PO_NAME,'zipcode':dataGeo[i].properties.ZIP5,'calls':newDict[dataGeo[i].properties.ZIP5]}; | |
}; | |
d3.select('#svgtwo') | |
.append('line') | |
.attr({ | |
x1:0, | |
y1:0, | |
x2:0, | |
y2:h, | |
"stroke-width":"1px", | |
"stroke":"black", | |
}); | |
//legend | |
svg.append("g") | |
.attr("class", "legendQuant") | |
.attr("transform", "translate(350,450)"); | |
var legend = d3.legend.color() | |
.labelFormat(d3.format(".2f")) | |
.useClass(true) | |
.scale(quantize); | |
svg.select(".legendQuant") | |
.call(legend); | |
};})(); | |
</script> | |
for more info or data vist <a href="http://data.saccounty.net/home">http://data.saccounty.net/home</a> | |
</body> | |
<html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment