d3 - load two specific columns from csv file - csv

I am trying to plot circles on a map based on data from csv files. I want the latitude and longitude from the csv file and plot a circle.
I am unable to long the two fields. I get an object undefined error. Here's my code so far:
Here's the link for the CSV file -
http://slate-interactives-prod.elasticbeanstalk.com/gun-deaths/getCSV.php
<html>
<head>
<meta charset="utf-8">
<link href="d3-geomap/css/d3.geomap.css" rel="stylesheet">
<script src="d3-geomap/vendor/d3.geomap.dependencies.min.js"></script>
<script src="d3-geomap/js/d3.geomap.min.js"></script>
</head>
<style>
path.unit:hover{
fill:#99d8c9;
}
</style>
<body>
<div id="map"></div>
</body>
</html>
<script>
var map = d3.geomap.choropleth()
.geofile('d3-geomap/topojson/countries/USA.json')
.projection(d3.geo.albersUsa)
.column('2012')
.unitId('fips')
.scale(1000)
.legend(true);
var width = 950,
height = 550;
// set projection
var projection = d3.geo.albersUsa();
// create path variable
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
d3.csv("data.csv", function(data) {
var coordinates = projection([data.lat,data.lng]);
svg.append("circle")
.attr("cx", coordinates[0])
.attr("cy", coordinates[1])
.attr("r", 5)
.style("fill", "red");
});
d3.select('#map')
.call(map.draw, map);
</script>

There are at least a couple of problems in your code. First the data object that d3.csv retrieves is an array. It's the elements of that array that will have properties such as .lat and .lng. So data.lat and data.lng are not defined.
I'm guessing that you want to create circles for each element in the array. You could do that by iterating through the array, e.g.
data.forEach(function(d) {
var coordinates = projection([d.lat, d.lng]);
// ...
});
That's not the normal D3 idiom (it's not using selections and .enter()) but it would work.
Secondly, CSV files are always read as text strings, even when the values are actually numbers. You'll want to convert from strings to numbers, so the code above really should be
var coordinates = projection([parseFloat(d.lat), parseFloat(d.lng)]);
As I said, there may be other problems with your code, but fixing those two should at least get you further along.

Related

canvasjs and coingecko api data

being new to plotting chart with the external api data and lack of knowldge leads me to ask
HOw to plot a chart with coingeko charts api data? link to get json formated api data is:
https://api.coingecko.com/api/v3/coins/ethereum/market_chart?vs_currency=btc&days=30
i had used this sample code and replace the link however only empty chart gets populated without plotting any data points
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript" src="https://canvasjs.com/assets/script/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<script type="text/javascript">
window.onload = function () {
var dataPoints = [];
var chart = new CanvasJS.Chart("chartContainer",{
title:{
text:"Rendering Chart with dataPoints from External JSON"
},
data: [{
type: "line",
dataPoints : dataPoints,
}]
});
$.getJSON("https://api.coingecko.com/api/v3/coins/mustangcoin/market_chart?vs_currency=btc&days=max&type=json", function(data) {
$.each(data, function(key, value){
dataPoints.push({x: value[0], y: parseInt(value[1])});
});
chart.render();
});
}
</script>
</head>
<body>
<div id="chartContainer" style="height: 300px; width: 100%;"></div>
</body>
</html>
The API returns:
{
prices: Array,
market_caps: Array,
total_volumes: Array,
}
First you need to select which data you want, you cannot mix them up together.
Secondly, you should create chart new CanvasJS.Chart after you have received the JSON result (in the function() {} body, not before that. Right now, it is uncertain whether the chart is actually getting the updated dataPoints, or is aware about it being updated after you have created the chart.
If you want to update the chart after creation you need to do what their docs says: https://canvasjs.com/docs/charts/basics-of-creating-html5-chart/updating-chart-options/

Using data from csv in nvd3 graph

I'm using my Ubuntu server to run automated speed tests and am recording the data in a csv file. I'd like to now plot all this data in a graph. The csv file is called data.csv in the same directory as index.html and it contains the following:
time,ping,down,up
1454190169992.8655,25.40,61.1,18.2
1454196940589.804,24.57,65.8,18.2
1454200093536.6118,26.39,66.8,18.2
1454235805528.2244,25.21,59.3,18.1
1454235966417.7297,25.01,59.4,18.2
1454236051628.0317,24.68,59.8,18.2
1454239827546.229,26.63,64.6,18.2
index.html currently looks like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="nv.d3.css" />
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="nv.d3.min.js"></script>
</head>
<body>
<svg id="chart" style="width:500; height:500;"></svg>
</body>
<script type="text/javascript">
d3.csv("data.csv", function(error, data){
console.log(data)
// create an empty object that nv is expecting
var exampleData = [
{
key: "totals",
values: []
}
];
// populate the empty object with your data
data.forEach(function (d){
d.value = +d.value
exampleData[0].values.push(d)
})
nv.addGraph(function() {
var chart = nv.models.lineChart()
.margin({left: 100}) //Adjust chart margins to give the x-axis some breathing room.
.useInteractiveGuideline(true) //We want nice looking tooltips and a guideline!
.transitionDuration(350) //how fast do you want the lines to transition?
.showLegend(true) //Show the legend, allowing users to turn on/off line series.
.showYAxis(true) //Show the y-axis
.showXAxis(true) //Show the x-axis
.x(function (d) { console.log(d); return d.time })
.y(function (d) { return d.ping })
d3.select('#chart')
.datum(exampleData)
.attr("id", function (d) { console.log(d); })
.transition().duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
});
</script>
</html>

D3 Choropleth Map CSV

I'm struggling getting my choropleth map to work. I have a CSV file of values and district names I want to match to my TopoJSON map. The data on the CSV map looks like this:
id, values
NAIROBI,50
MOMBASA,10
KWALE,20
KILIFI,40
TANA RIVER,50
LAMU,10
The id column is for names of districts in Kenya, the values are arbitrary and are just meant to generate colors according to the domain set for the threshold scale I am using. For some reason the colors just won't generate. Here is the rest of my code. Please let me know where I am going wrong? I keep trying to fix it to no avail:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="d3.v3.js"></script>
<script type="text/javascript" src="js/topojson.js"></script>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
<link rel="stylesheet" href="css/bootstrap.css" media="screen">
</head>
<body>
<div class="row">
<header class="span12">
<h1>Aphellion Activity 1 - Kenya Maps</h1>
<h3>The goal of this activity is generate two maps one drawn with D3.js using GeoJSON to generates the paths, the other drawn using TopoJSON to generate the paths.</h3>
</header>
</div>
</br>
<div class="row">
<div class="span6" id="Map1">
<p>This first map of Kenya was made using TopoJSON.</p>
</div>
<div class="span6" id="Map2">
<p>This second map of Kenya was made using GeoJSON.</p>
</div>
</div>
</body>
<script type="text/javascript">
var width = 460;
var height = 400;
//Setting the color domains for the choropleth maps
var color = d3.scale.threshold()
.domain([10, 20, 30, 40, 50])
.range(["#9e9ac8", "756bb1", "dadaeb", "bcbddc", "#E82D0C"]);
//TopoJSON Map
//new projection
var projection = d3.geo.mercator()
.center([36.8000, 1.2667])
.scale([1000])
.translate([width/2, height/2]);
var path = d3.geo.path().projection(projection);
//Drawing Choropleth
var svg = d3.select("div#Map1")
.append("svg")
.attr("width", width)
.attr("height", height);
var g = svg.append("g")
.call(d3.behavior.zoom()
.scaleExtent([1, 10])
.on("zoom", zoom));
d3.json("js/output.json", function(error, topology) {
d3.csv("js/Schools.csv", function(error, Schools) {
var rateById = {};
Schools.forEach(function (d) {
rateById[d.id] = +d.values;
});
g.append("g")
.attr("class", "districts")
.selectAll("path")
.data(topojson.feature(topology, topology.objects.kenya).features)
.enter()
.append("path")
.attr("d", path)
.style("fill", function(d) {
return color(rateById[d.id]);
});
});
});
//Draw a rect around the map
svg.append("rect").attr("width", width).attr("height", height).style("stroke", "black").style("fill", "none")
;
function zoom() {
g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")")};
</script>
</html>
You were very, very close. You were returning an empty hash, return rateById = {}; instead of declaring it for use in your code, var rateById = {};.
I have updated the PLUNK with the correct references to libraries and added CSS styling to it.
The only other change is that I used more contrasting colors for demo purposes, but you can uncomment your original colors and it will work just fine.

Trouble Binding JSON subarrays in d3.js

I guess anyone who monitors the d3 questions is getting used to seeing me this week (this is my first time using d3) so here goes another question. I am fetching data via php/ajax but I have placed a sample as hard code below. I wish to bind the fineBinSummary data to a bar chart but can't seem to figure out how. When I inspect the html it makes it as far as setting up the svg and then stops when I start to try to bind data to it.
I successfully bound the detail data (code not shown, just the JSON) but can't get the fineBinSummary data to bind in the same manner. I also will need to extract the length of the fineBinSummary array (you can see that I've just made it the width / 5 but there won't always be 5 bars in the chart. Any assistance is much appreciated.
(document).ready(function() {
var data = [
{"Id":"93439440411",
"detail":[{"fineBin":"UNCLASSIFIED","x":"-142000.0","y":"-21000.0","imageId":null,"serverId":null,"fileSpec":null,"color":"HotPink"},
{"fineBin":"UNCLASSIFIED","x":"-142000.0","y":"16000.0","imageId":null,"serverId":null,"fileSpec":null,"color":"HotPink"},
{"fineBin":"UNCLASSIFIED","x":"-141000.0","y":"-15000.0","imageId":null,"serverId":null,"fileSpec":null,"color":"HotPink"},
{"fineBin":"UNCLASSIFIED","x":"-141000.0","y":"24000.0","imageId":null,"serverId":null,"fileSpec":null,"color":"HotPink"},
{"fineBin":"UNCLASSIFIED","x":"-141000.0","y":"27000.0","imageId":null,"serverId":null,"fileSpec":null,"color":"HotPink"},
{"fineBin":"UNCLASSIFIED","x":"-140000.0","y":"-15000.0","imageId":null,"serverId":null,"fileSpec":null,"color":"HotPink"}],
"fineBinSummary":[{"fineBin":"UNCLASSIFIED","count":8212},{"fineBin":"SMALL_PARTICLE","count":104},{"fineBin":"RESIDUE","count":68},
{"fineBin":"FALSE","count":16},{"fineBin":"258","count":12}]},
{"Id":"93439440419",
"detail":[{"fineBin":"UNCLASSIFIED","x":"-142839.40900000001","y":"20448.394","imageId":null,"serverId":null,"fileSpec":null,"color":"HotPink"},
{"fineBin":"UNCLASSIFIED","x":"-142546.65599999999","y":"26731.720000000001","imageId":null,"serverId":null,"fileSpec":null,"color":"HotPink"},
{"fineBin":"UNCLASSIFIED","x":"-142499.136","y":"-24443.516","imageId":null,"serverId":null,"fileSpec":null,"color":"HotPink"},
{"fineBin":"UNCLASSIFIED","x":"-142267.68799999999","y":"32411.870999999999","imageId":null,"serverId":null,"fileSpec":null,"color":"HotPink"},
{"fineBin":"UNCLASSIFIED","x":"-142000.0","y":"-33000.0","imageId":null,"serverId":null,"fileSpec":null,"color":"HotPink"}],
"fineBinSummary":[{"fineBin":"UNCLASSIFIED","count":8212},{"fineBin":"SMALL_PARTICLE","count":104},{"fineBin":"RESIDUE","count":68},
{"fineBin":"FALSE","count":16},{"fineBin":"258","count":12}]}]
//Constants
var squareSide = 400;
var height = squareSide / 2.0;
var barWidth = squareSide / 5;
//begin building bootstrap courousel stack
var slides = d3.select(".carousel-inner").selectAll('div')
.data(data)
.enter()
.append("div")
.attr("class","item")
.append("div")
.attr("class","container-fluid")
.append("div")
.attr("class","row");
//Make the first slide the active slide
d3.selectAll(".item").classed('active', function(d, i) { return i == 0; });
//Build the image side of the slide
var imageSide = slides.append("div")
.attr("class","col-lg-6 wafer-and-pareto");
//build final location for div that will hold the histogram
var paretoBox = imageSide.append("div")
.attr("class","row")
.append("div")
.attr("class","col-lg-12")
.append("div")
.attr("class","pareto-box")
.append("svg")
.attr("class","chart")
.attr("width",squareSide)
.attr("height",squareSide / 2.0);
Seems to be working up to this point based on reviewing the html but does not successfully execute the code below:
var bar = paretoBox.selectAll("g")
.data(function(d) {return data.fineBinSummary})
.enter()
.append("g")
.attr("transform",function(d,i) {
return "translate(" + i * barWidth + ",0)";
});
bar.append("rect")
.attr("y",function(d) {
return y(d.count);
})
.attr("height",function(d) {
return height - y(d.count)
})
.attr("width",barWidth - 1);
var y = d3.scale.linear()
.range([height,0])
.domain([0,d3.max(data.fineBinSummary,function(d) {
return d.count;
})]);
})
There are just two small problems with your code. First, in your nested selection, you are referencing the original data instead of the part bound to the current element. Instead of
var bar = paretoBox.selectAll("g")
.data(function(d) {return data.fineBinSummary})
use
var bar = paretoBox.selectAll("g")
.data(function(d) {return d.fineBinSummary})
Second, the max element for your scale is determined incorrectly -- data doesn't have a fineBinSummary member. The code should look like this:
var y = d3.scale.linear()
.range([height,0])
.domain([0, d3.max(data, function(d) {
return d3.max(d.fineBinSummary, function(e) { return e.count; });
})]);

Finding coordinates of a point in OpenLayers

How can one get the coordinates of a particular point on a map in OpenLayers?
Handle click event on map Click handler. Here is one of many sample codes you can find in OpenLayers mailing list archives:
map.events.register('click', map, handleMapClick);
function handleMapClick(e)
{
var lonlat = map.getLonLatFromViewPortPx(e.xy);
// use lonlat
// If you are using OpenStreetMap (etc) tiles and want to convert back
// to gps coords add the following line :-
// lonlat.transform( map.projection,map.displayProjection);
// Longitude = lonlat.lon
// Latitude = lonlat.lat
}
<html>
<head>
<script src="http://openlayers.org/api/OpenLayers.js"></script>
<script type="text/javascript">
function init(){
map = new OpenLayers.Map('map');
base_layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
"http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
map.addLayer(base_layer);
map.zoomToMaxExtent();
map.events.register('click', map, handleMapClick);
}
function handleMapClick(evt)
{
var lonlat = map.getLonLatFromViewPortPx(evt.xy);
// use lonlat
alert(lonlat);
}
</script>
</head>
<body onload="init()">
Hello Map.<br />
<div id="map"></div>
</body>
</html>
#mloskot Your answer is great you had a mistake with the evt variable.
Just added the html markup to make it a working page.