How to plot lat/long pairs over map in D3.js - d3.js

I'm having a problem plotting points from a geoJSON file over a map using D3.js. The map is rendering fine, but the points are not showing up. I'm not receiving any error messages at this time.
I'm following along with this tutorial but using my own geoJSON file to plot the data.
This is what I have:
var width = 960,
height = 500;
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var g = svg.append("g");
var projection = d3.geoAlbers()
.scale(1000)
.translate([width / 2, height / 2]);
var path = d3.geoPath()
.projection(projection);
d3.queue()
.defer(d3.json, 'states.json') // Load US States
.defer(d3.json, 'trump_geoJson.json') // Load tweet lat/long data
.await(makeMyMap); // Run 'ready' when JSONs are loaded
function makeMyMap(error,states,tweets) {
svg.append('path')
.datum(topojson.feature(states, states.objects.usStates))
.attr('d', path)
.attr('class', 'states');
svg.selectAll('.tweets')
.data(tweets.features)
.enter()
.append('path')
.attr('d',path)
.attr('class', 'tweets');
}
I'm expecting about 600 points to be plotted, but getting none.
The json file trump_geoJson looks like:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": 0,
"properties": {
"primary_geo": "Utah, USA",
"tag": "#Bernie",
"text": "text",
"user_id": "id"
},
"geometry": {
"type": "Point",
"coordinates": [
39.32373809814453,
-111.67823791503906
]
}
},
{
"type": "Feature",
"id": 1,
"properties": {
"primary_geo": "New York, NY",
"tag": "#Bernie",
"text": "text",
"user_id": "id"
},
"geometry": {
"type": "Point",
"coordinates": [
40.71455001831055,
-74.00714111328125
]
}
},... ]

Your geojson uses the wrong coordinate convention. You have:
"coordinates": [ latitude, longitude ]
But, you must use:
"coordinates": [ longitude, latitude ]
From the spec:
Point coordinates are in x, y order (easting, northing for projected
coordinates, longitude, and latitude for geographic coordinates)
It is funny that the spec considers eastings and northings for projected coordinates given the spec also states geojson must use unprojected (lat/long) coordinates using the WGS84 datum
Here's a demo of the first two items in your geojson feature collection:
var data = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-111.6782379150,39.32373809814]
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-74.00714111328,40.71455001831]
}
}]};
var width = 500,
height = 300;
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var projection = d3.geoAlbers()
.scale(600)
.translate([width / 2, height / 2]);
var path = d3.geoPath()
.projection(projection);
d3.json("https://unpkg.com/world-atlas#1/world/110m.json", function(error, world) {
if (error) throw error;
svg.append("path")
.attr("d", path(topojson.mesh(world)))
.attr("fill","none")
.attr("stroke","black")
.attr("stroke-width",1);
svg.selectAll('.tweets')
.data(data.features)
.enter()
.append('path')
.attr('d',path)
.attr('class', 'tweets');
});
.tweets {
fill: red;
opacity: 0.7;
}
<script src="http://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="https://d3js.org/d3-queue.v2.min.js"></script>

Related

Root element is not showing its children in sunburst

I am trying to make a sunburst by following the 3-part tutorial on https://bl.ocks.org/denjn5/3b74baf5edc4ac93d5e487136481c601 My json contains sell information based on country and product division. I am trying to show in the first layer sell based on country and in the 2nd layer sell based on product division. My Json file looks like this:
{
"country": "All",
"shares":[
{
"country": "at",
"shares":[
{
"productdivision": "accessorie",
"label": 53222
},
{
"productdivision": "apparel",
"label": 365712
},
{
"productdivision": "footwear",
"label": 523684
}
]
},
{
"country": "be",
"shares":[
{
"productdivision": "accessorie",
"label": 57522
},
{
"productdivision": "apparel",
"label": 598712
},
{
"productdivision": "footwear",
"label": 52284
}
]
},
{
"country": "DE",
"shares":[
{
"productdivision": "accessorie",
"label": 56982
},
{
"productdivision": "apparel",
"label": 55312
},
{
"productdivision": "footwear",
"label": 67284
}
]
},
{
"country": "Fr",
"shares":[
{
"productdivision": "accessorie",
"label": 5862
},
{
"productdivision": "apparel",
"label": 45312
},
{
"productdivision": "footwear",
"label": 26284
}
]
}
]
}
This json file's name is kpiDrillDown2.json and I call it in my code with d3.json(). I have made slight changes to the code to work for my data. The code is as follows:
<html>
<head>
<style>
#import url('https://fonts.googleapis.com/css?family=Raleway');
body {
font-family: "Raleway", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<svg></svg>
<script>
//initialize variables
var width = 500;
var height = 500;
var radius = Math.min(width, height) / 2;
var color = d3.scaleOrdinal(d3.schemeCategory20b);
//setting up svg workspace
var g = d3.select('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
//formatting the data
var partition = d3.partition()
.size([2 * Math.PI, radius]);
function draw(nodeData){
debugger;
//finding the root node
var root = d3.hierarchy(nodeData)
.sum(function (d) { return d.label});
//calculating each arc
partition(root);
var arc = d3.arc()
.startAngle(function (d) { return d.x0; })
.endAngle(function (d) { return d.x1; })
.innerRadius(function (d) { return d.y0; })
.outerRadius(function (d) { return d.y1; });
g.selectAll('g')
.data(root.descendants())
.enter()
.append('g')
.attr("class", "node")
.append('path')
.attr("display", function (d) { return d.depth ? null : "none"; })
.attr("d", arc)
.style('stroke', '#fff')
.style("fill", function (d) { return color((d.parent ? d : d.parent).data.productdivision); })
g.selectAll(".node")
.append("text")
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")rotate(" + computeTextRotation(d) + ")"; })
.attr("dx", "-20")
.attr("dy", ".5em")
.text(function(d) { return d.parent ? d.data.productdivision : "" });
function computeTextRotation(d) {
var angle = (d.x0 + d.x1) / Math.PI * 90;
// Avoid upside-down labels
return (angle < 90 || angle > 270) ? angle : angle + 180;
}
}
d3.json('kpiDrillDown3.json', draw);
</script>
</body>
</html>
I put a debbuger in the draw functin to inspect root element. Root doesn't have any children. This is what I see in the console:
When I continue it gives me the error:"Cannot read property 'data' of null". As shown in console, root doesn't have children. My question is, do I need to change my json data format to make root recogninze the chilren, or am I doing something wrong. I am new to d3js and basically by getting the source code and modifying it, I am making my way through. This is the error in console:
I appreciate your help and thank you very much.
According to the API:
The specified children accessor function is invoked for each datum, starting with the root data, and must return an array of data representing the children, or null if the current datum has no children. If children is not specified, it defaults to:
function children(d) {
return d.children;
}
However, in your data structure, you don't have children, but shares instead.
So, the hierarchy should be:
var root = d3.hierarchy(data, function(d) {
return d.shares;
})
Pay attention to the fact that in the JSON of that tutorial you linked (just like in the API's example) the children's array is named children.
Here is a demo, look at the console (your browser's console, not the snippet one):
var data = {
"country": "All",
"shares": [{
"country": "at",
"shares": [{
"productdivision": "accessorie",
"label": 53222
},
{
"productdivision": "apparel",
"label": 365712
},
{
"productdivision": "footwear",
"label": 523684
}
]
},
{
"country": "be",
"shares": [{
"productdivision": "accessorie",
"label": 57522
},
{
"productdivision": "apparel",
"label": 598712
},
{
"productdivision": "footwear",
"label": 52284
}
]
},
{
"country": "DE",
"shares": [{
"productdivision": "accessorie",
"label": 56982
},
{
"productdivision": "apparel",
"label": 55312
},
{
"productdivision": "footwear",
"label": 67284
}
]
},
{
"country": "Fr",
"shares": [{
"productdivision": "accessorie",
"label": 5862
},
{
"productdivision": "apparel",
"label": 45312
},
{
"productdivision": "footwear",
"label": 26284
}
]
}
]
};
var root = d3.hierarchy(data, function(d) {
return d.shares;
})
.sum(function(d) {
return d.label
});
console.log(root)
<script src="https://d3js.org/d3.v4.min.js"></script>

d3js v4 hierarchical edge bundling

Im trying to make a hierarchical edge bundling like this using d3 v4. I use d3.curveBundle to make the line curved. But in my project, the line doesn't seem to be curved.
What I get is a straight line like this:
This is my code:
var data = {
"name": "Eve",
"children": [
{
"name": "Cain"
},
{
"name": "Seth",
"children": [
{
"name": "Enos"
},
{
"name": "Noam"
}
]
},
{
"name": "Abel"
},
{
"name": "Awan",
"children": [
{
"name": "Enoch"
}
]
},
{
"name": "Azura"
}
]
};
var cluster = d3.cluster()
.size([360, 120]);
var nodes = cluster(d3.hierarchy(data));
var links = nodes.links();
var svg = d3.select("div.radial-network")
.append("svg")
.attr("width", "100%")
.attr("height", "300")
.attr("transform", "translate(120,120)");
const line = d3.radialLine()
.curve(d3.curveBundle.beta(0.95))
.angle(function(d,i){ return d.x*Math.PI/180;})
.radius(function(d,i) {return d.y;});
const edges = svg.selectAll('.link').data(links);
edges.enter().append('path')
.attr('class', 'link')
.attr('stroke', 'red')
.attr('d', function(d, i) {return line(d.source.path(d.target));});

Trying to add a second parent node to a child node using d3 tree chart library

I'm trying to create a D3 Tree, and able to get the task done to some extent, but in my situation, there can be more than 1 parent node to a single node.
But as I've learned, I still need to start off with one root node to build the tree, and I did that and was able to build the tree, and now want to add a second node to a tree node.
var data = [{
"children": [{
"children": [{
"children": [{
"children": [
],
"name": "Hierarchy Child 5",
"parent": "Hierarchy Sibling",
"relation": "Parent Of",
"rid": "a059000000VBecUAAT"
}],
"name": "Hierarchy Sibling",
"parent": "Hierarchy Parent",
"relation": "Parent Of",
"rid": "a059000000VBKeYAAX"
}, {
"children": [{
"children": [
],
"name": "Hierarchy Child 1",
"parent": "ACME",
"relation": "Parent Of",
"rid": "a059000000VBKf7AAH"
}, {
"children": [
],
"name": "Hierarchy Child 2",
"parent": "ACME",
"relation": "Parent Of",
"rid": "a059000000VBKfCAAX"
}, {
"children": [
],
"name": "Hierarchy Child 3",
"parent": "ACME",
"relation": "Parent Of",
"rid": "a059000000VBKfHAAX"
}, {
"children": [
],
"name": "Hierarchy Child 4",
"parent": "ACME",
"relation": "Parent Of",
"rid": "a059000000VBKfMAAX"
}],
"name": "ACME",
"parent": "Hierarchy Parent",
"relation": "Parent Of",
"rid": "a059000000VBKeJAAX"
}],
"name": "Hierarchy Parent",
"parent": "This is Test Second Parent Node",
"relation": "Parent Of",
"rid": "a059000000VBKeOAAX"
}, {
"children": [
],
"name": "Hierarchy Uncle",
"parent": "Hierarchy Grandparent",
"relation": "Parent Of",
"rid": "a059000000VBKedAAH"
}, {
"children": [
],
"name": "Hierarchy Great Uncle",
"parent": "Hierarchy Grandparent",
"relation": "Parent Of",
"rid": "a059000000VBKenAAH"
}],
"name": "Hierarchy Grandparent",
"parent": "null",
"relation": "Parent Of",
"rid": "a059000000VBKeTAAX"
}];
// *********** Convert flat data into a nice tree ***************
// create a name: node map
var dataMap = data.reduce(function(map, node) {
map[node.name] = node;
return map;
}, {});
// create the tree array
var treeData = [];
data.forEach(function(node) {
// add to parent
var parent = dataMap[node.parent];
if (parent) {
// create child array if it doesn't exist
(parent.children || (parent.children = []))
// add node to child array
.push(node);
} else {
// parent is null or missing
treeData.push(node);
}
});
// ************** Generate the tree diagram *****************
var margin = {
top: 20,
right: 120,
bottom: 20,
left: 120
},
width = 960 - margin.right - margin.left,
height = 500 - margin.top - margin.bottom;
var i = 0;
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) {
return [d.y, d.x];
});
var svg = d3.select("div#chart-container").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
root = treeData[0];
update(root);
function update(source) {
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// Normalize for fixed-depth.
nodes.forEach(function(d) {
d.y = d.depth * 180;
});
// Declare the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d) {
return d.id || (d.id = ++i);
});
// Enter the nodes.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.y + "," + d.x + ")";
});
nodeEnter.append("circle")
.attr("r", 10)
.style("fill", "#fff");
nodeEnter.append("text")
.attr("x", function(d) {
return d.children || d._children ? -13 : 13;
})
.attr("dy", ".35em")
.attr("text-anchor", function(d) {
return d.children || d._children ? "end" : "start";
})
.text(function(d) {
return d.name;
})
.style("fill-opacity", 1);
// Declare the links…
var link = svg.selectAll("path.link")
.data(links, function(d) {
return d.target.id;
});
// Enter the links.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", diagonal);
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 3px;
}
.node text {
font: 12px sans-serif;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="chart-container">
</div>
As we can see, the code runs fine and tree is generating but my JSON data array has a second parent on node with name as Hierarchy Parent has a parent specified as This is Test Second Parent Node but this node does not appear on tree.
This Image is what I'm trying to generate as output:
Take a look at this example
http://bl.ocks.org/robschmuecker/6afc2ecb05b191359862
If that doesn't help, you might want to take a look at the force directed graph
https://bl.ocks.org/mbostock/4062045
Also take a look at cytoscape, very similar to d3 but it deals with networks (graph data structure) as well as trees http://js.cytoscape.org/demos/aedff159b0df05ccfaa5/

trying to configure geojson file for a particular map

I'm trying to configure a map that shows a view of the US with some of the buttom of Canada and some of the top of Mexico. I did a basic capture of this in www.geojson.io:
http://geojson.io/#id=gist:anonymous/b2f65ddc2a28013b0c9c7ecab5d7427f&map=4/39.37/-97.16
How can I display this in a browser map using d3.js? I'm able to display a browser map of the world using world-110m.json which seems to be a commonly used geojson file:
https://gist.githubusercontent.com/mbostock/4090846/raw/d534aba169207548a8a3d670c9c2cc719ff05c47/world-110m.json
Here's the d3 code I'm using to display the geojson as a browser map:
d3.json("json/world-110m.json", function (error, topology) {
if (error) return console.warn(error);
g.selectAll("path")
.data(topojson.object(topology, topology.objects.countries)
.geometries)
.enter()
.append("path")
.attr("d", path)
});
World-110m.json seems to have a lot of additional info I don't need because I just need to display a flat map of the area captured in my geojson.io map above. Do I need to build out my geojson, update my d3 code or both?
I'm not sure what geojson.io is doing but the geojson it's returning (two identical polygons) doesn't seem to correlate to anything resembling your selection.
For what it is worth, here's the "map" from that geojson:
<!DOCTYPE html>
<html>
<head>
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<script>
var geoJson = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[-129.0234375,
23.160563309048314
],
[-129.0234375,
52.53627304145948
],
[-65.302734375,
52.53627304145948
],
[-65.302734375,
23.160563309048314
],
[-129.0234375,
23.160563309048314
]
]
]
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[-129.0234375,
23.160563309048314
],
[-129.0234375,
52.53627304145948
],
[-65.302734375,
52.53627304145948
],
[-65.302734375,
23.160563309048314
],
[-129.0234375,
23.160563309048314
]
]
]
}
}]
};
var width = 960,
height = 600;
var projection = d3.geo.albersUsa()
.scale(500)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("g")
.selectAll("path")
.data(geoJson.features)
.enter().append("path")
.attr("d", path);
</script>
</body>
</html>

Projection path there; but the path is only 1px by 1px?

I am trying to project a geojson file, which has a default projection type.
My path lines are appearing in the console inspector:
But the lines are only 1px by 1px, so they do not appear. What is happening?
My code:
var mapWidth = 60;
var mapHeight = 90;
var projection = d3.geo.mercator().scale([100]);
var path = d3.geo.path()
.projection(projection);
(function run() {
d3.json("./data/output.geojson", function(error, map) {
var chart = d3.select("#charts").selectAll("svg")
.data(map.features)
.enter()
.append("svg")
.attr("width", mapWidth)
.attr("height", mapHeight)
.append("g")
chart
.append("path")
.attr("d", path)
.style("fill","steelblue");
});
})()
Geojson is as following (this is a snippet):
{
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { "neighborhood": "Battery Park City", "boroughCode": "1", "borough": "Manhattan", "#id": "http:\/\/nyc.pediacities.com\/Resource\/Neighborhood\/Battery_Park_City" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -74.013754000000176, 40.71369 ], [ -74.014262000000187, 40.710928000000195 ], [ -74.016542000000186, 40.704733000000275 ], [ -74.016174, 40.702572000000174 ], [ -74.01563, 40.701862000000233 ], [ -74.015127, 40.701390000000259 ], [ -74.014008, 40.701043000000325 ], [ -74.013959214170356, 40.700965860994032 ], [ -74.01410490300087, 40.700510828386832 ], [ -74.

Resources