Unable to create bar chart from d3 using URL - json

I am trying to create bar chart from json file which is a URL but i am unable to do so please help me, as i am new to d3. The code is here please tell me where i am making mistake.
var width = 960,
height = 500;
var y = d3.scale.linear().range([height, 0]);
var chart = d3.select("#chart")
.append("svg")
.attr("width", width)
.attr("height", height);
generateChart();
function generateChart() {
d3.json('http://dataserver.org:8009/topic/domain/cancer',
function(error, data) {
y.domain([0, d3.max(data, function(d) {
return d.occurrence
})]);
var barWidth = width / data.length; //width of each bar
var bar = chart.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function(d, i) {
return "translate(" + i * barWidth + ", 0)";
});
bar.append("rect")
.attr("y", function(d) {
return y(d.occurrence);
})
.attr("height", function(d) {
return height - y(d.occurrence);
})
.attr("width", barWidth - 1);
bar.append("text")
.attr("x", barWidth / 2)
.attr("y", function(d) {
return y(d.occurrence) - 10;
})
.attr("dy", ".75em")
.text(function(d) {
return d.authorName;
});
});
};

It is not a problem of cross domain as I checked your API. Assuming that you are fetching d3.js from CDN, I am suggesting a change. Your chart will depend on "institute" as it is containing all the required values for chart. So I changed it as per structure your API's response.
**in some case data was coming as "undefined" so I am fetching d3.js from CDN
Here is whole modified file:-
function generateChart() {
d3.json('http://srvgal78.deri.ie:8009/topic/domain/cancer',
function(error, data) {
data = data.institute;
y.domain([0, d3.max(data, function(d) {
return d.occurrence
})]);
var barWidth = width / data.length; //width of each bar
var bar = chart.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function(d, i) {
return "translate(" + i * barWidth + ", 0)";
});
bar.append("rect")
.attr("y", function(d) {
return y(d.occurrence);
})
.attr("height", function(d) {
return height - y(d.occurrence);
})
.attr("width", barWidth - 1);
bar.append("text")
.attr("x", barWidth / 2)
.attr("y", function(d) {
return y(d.occurrence) - 10;
})
.attr("dy", ".75em")
.text(function(d) {
return d.authorName;
});
});
};

Related

D3 v4 simple bar chart - date always returns null. timeParsing/format issue

For some odd reason, my dates won't properly show up on my bar chart. When checking for errors, my dates always show up as "null" in the console. My professor and I have tried re-arranging the format of the code regarding the dates, as well as the .csv spreadsheet itself.
The gradient still works fine, but ever since we've been stumped on implementing the dated timeline feature, the bar chart info is out of view, as well.
I'm using the core sample 'Dogecoin' from this website:
https://coinmetrics.io/data-downloads/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>DOGECOIN BAR CHART</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<style type="text/css">
</style>
</head>
<body>
<script type="text/javascript">
var w = 1000;
var h = 500;
var margin = ({
top: 20,
right: 20,
bottom: 30,
left: 50
});
var svgMAIN = d3.select("body")
.append("svg")
.attr("height", h - margin.top - margin.bottom)
.attr("width", w - margin.left - margin.right);
var g = svgMAIN.append("g").attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
var gradient = svgMAIN.append("defs")
.append("linearGradient")
.attr("id", "gradient")
.attr("x1", "0%")
.attr("y1", "0%")
.attr("x2", "100%")
.attr("y2", "100%")
.attr("spreadMethod", "pad");
gradient.append("stop")
.attr("offset", "0%")
.attr("stop-color", "#3f51b5")
.attr("stop-opacity", 1);
gradient.append("stop")
.attr("offset", "100%")
.attr("stop-color", "#009688")
.attr("stop-opacity", 0);
svgMAIN.append("rect")
.attr("width", w)
.attr("height", h)
.style("fill", "url(#gradient)");
var price = [];
var date = [];
var fixTime = d3.timeParse("%e-%b-%y");
var x = d3.scaleTime().range([0, w]);
var y = d3.scaleLinear().range([h, 0]);
d3.csv("doge.csv", function(error, data) {
data.map(function(d) {
d.date = fixTime(d.date);
price.push(d.priceUSD);
y.domain([0, d3.max(data, function(d) {
return d.priceUSD;
})]);
x.domain(d3.extent(data, function(d) {
return d.date;
}));
});
svgMAIN.append("g")
.attr("transform", "translate(0," + h + ")")
.call(d3.axisBottom(x))
g.append("g")
.call(d3.axisLeft(y))
.append("text")
.attr("fill", "#000")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("Price ($)");
var rect = svgMAIN.selectAll("rect")
.data(price)
.enter()
.append("rect")
.attr("x", function(d, i) {
return i * (w / price.length);
})
.attr("y", function(d) {
return d;
})
.attr("width", w / price.length)
.attr("height", function(d) {
return d;
})
.attr("fill", "midnightblue")
.on("mouseover", mouseOverPrice)
.on("mouseout", mouseOutPrice);
function mouseOverPrice(d, i) {
d3.select(this).raise()
.attr("fill", "white");
svgMAIN.append("text")
.attr("id", "priceValue")
.attr("x", "50")
.attr("y", "150")
.text("$" + d)
.attr("font-family", "sans-serif")
.attr("font-size", "150px")
.attr("fill", "white")
.attr("font-weight", "bold");
};
function mouseOutPrice(d, i) {
d3.select(this).attr("fill", "midnightblue");
d3.select("#priceValue").remove();
};
});
</script>
</body>
</html>

Legend text background change on mouse-hover over d3 doughnut chart

I have one doughnut chart whose values display on mouse-hover. But, I want to change the legend text background while hovering over the respective doughnut chart area.
return {
restrict: 'E',
scope: {
values: '='
},
link: function (scope, element, attrs) {
scope.$watch('values', function(values) {
var data = [];
if(values) {
console.log('values from directive: ', values);
var w = 700,
h = 700,
r = 290,
inner = 190,
color = d3.scale.category20();
data=values;
var total = d3.sum(data, function(d) {
return d3.sum(d3.values(d));
});
var vis = d3.select("#pieChartsD3")
.append("svg:svg")
.data([data])
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" +320+ "," +320+ ")")
var textTop = vis.append("text")
.attr("dy", ".35em")
.style("text-anchor", "middle")
.attr("class", "textTop")
.text( "TOTAL" )
.attr("y", -10),
textBottom = vis.append("text")
.attr("dy", ".35em")
.style("text-anchor", "middle")
.attr("class", "textBottom")
.text(total.toFixed(0) )
.attr("y", 10);
var arc = d3.svg.arc()
.innerRadius(inner)
.outerRadius(r);
var arcOver = d3.svg.arc()
.innerRadius(inner + 20)
.outerRadius(r + 20);
var pie = d3.layout.pie()
.value(function(d) { return d.val; });
var arcs = vis.selectAll("g.slice")
.data(pie)
.enter()
.append("svg:g")
.attr("class", "slice")
.style('word-wrap', 'break-word')
.on("mouseover", function(d) {
d3.select(this).select("path").transition()
.duration(200)
.attr("d", arcOver)
textTop.text(d3.select(this).datum().data.name)
.style('fill', 'red')
.attr("y", -10);
textBottom.text(d3.select(this).datum().data.val.toFixed(0))
.style('fill', 'blue')
.attr("y", 10);
})
.on("mouseout", function(d) {
d3.select(this).select("path").transition()
.duration(100)
.attr("d", arc);
textTop.text( "TOTAL" )
.attr("y", -10);
textBottom.text(total.toFixed(0));
});
arcs.append("svg:path")
.attr("fill", function(d, i) { return color(i); } )
.attr("d", arc);
console.log("datas length: "+data.length)
var legend = d3.select("#legend").append("svg")
.attr("class", "legend")
.attr("width", 400)
.attr("height", 20*data.length)
.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("width", 18)
.attr("height", 18)
.style("fill", function(d, i) { return color(i); });
legend.append("text")
.attr("x", 24)
.attr("y", 9)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
}
})
}
}
(BTW I'm inferring about your request because you haven't explicitly stated a question. With that said...)
Inside the .on("mouseover", function(d) { block, add another section:
legend.filter(function(l){
l === d; // remember d is the value bound to the donut segment
})
.attr("fill","yellow")
And be sure to write the logic to undo it, by setting fill back to grey or none, in .on("mouseout".

building d3 force directed graph using dynamic json data

my current D3 with static json looks like
var graph = {
"nodes":[
{"name":"User Login","group":1},
{"name":"Appointments","group":1},
{"name":"Store Visit","group":1},
{"name":"Visit History","group":1},
{"name":"Resume Store Visit","group":1}
],
"links":[
{"source":1,"target":0,"value":1},
{"source":2,"target":0,"value":8},
{"source":3,"target":0,"value":10},
{"source":3,"target":2,"value":6},
{"source":4,"target":0,"value":1}
]
};
var width = 960,
height = 500;
var color = d3.scale.category20();
var force = d3.layout.force()
.charge(-120)
.linkDistance(300)
.size([width, height]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
force
.nodes(graph.nodes)
.links(graph.links)
.start();
svg.append("svg:defs").selectAll("marker")
.data(["end"]) // Different link/path types can be defined here
.enter().append("svg:marker") // This section adds in the arrows
.attr("id", String)
.attr("viewBox", "0 -5 10 10")
.attr("refX", 15)
.attr("refY", -1.5)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");
var link = svg.selectAll(".link")
.data(graph.links)
.enter().append("line")
.attr("class", "link")
.attr("marker-end", "url(#end)")
.style("stroke-width", function(d) {
return Math.sqrt(d.value);
});
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter()
.append("g")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
})
.call(force.drag);
node.append("rect")
.attr("class", "node")
.attr("width", 100)
.attr("height", 35)
.style("fill", function(d) {
return color(d.group);
})
.style("stroke", "black")
.style("stroke-width", "1px");
node.append("text")
.text(function(d) {
return d.name + '(' + d.group + ')';
})
.style("font-size", "12px")
.attr("dy", "1em");
node.append("title")
.text(function(d) {
return d.name;
});
force.on("tick", function() {
link.attr("x1", function(d) {
return d.source.x;
})
.attr("y1", function(d) {
return d.source.y;
})
.attr("x2", function(d) {
return d.target.x;
})
.attr("y2", function(d) {
return d.target.y;
});
node.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
});
</script>
I want to move the static data to move to a js file and fetch it using my rest service like i am doing for other morris charts where the script looks like
$.ajax({ url: 'http://127.0.0.1:7101/MUDRESTService/rest/v1/meventsbydaybar?onlyData=true&limit=99',
type: 'get',
dataType: 'json',
success: function(output) {
var ddata = JSON.stringify(output.items);
var arr = JSON.parse(ddata);
bar.setData(arr);
}
});
Please advise how to use my above rest service as a source for the d3 graph
using
var data; // a global
d3.json("http://127.0.0.1:7101/MUDRESTService/rest/v1/mudstats?onlyData=true", function(error, json) {
data = json;
});
worked for me

D3 chart with JSON web service

I am trying to make the following bar chart from this tutorial. The tutorial utilizes TSV files, but I have modified the code for JSON. I have checked that the endpoint http://localhost:3000/graphs/data from my Node / Express service I created is indeed returning JSON, which can be seen below. The proper D3 libraries are also being included. After checking all this, I cannot get the chart to render.
The goal is to have route on the x-axis and count on the y-axis. Any suggestions would be greatly appreciated.
JSON Response:
[{"route":"9","count":273},{"route":"49","count":242},{"route":"151","count":221},{"route":"8","count":220},{"route":"3","count":213},{"route":"82","count":209},{"route":"79","count":206},{"route":"N5","count":206},{"route":"62","count":206},{"route":"4","count":202}]
Bar Chart Code
<script>
var margin = {top: 40, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var formatPercent = d3.format(".0%");
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<strong>Count:</strong> <span style='color:red'>" + d.count + "</span>";
})
var svg = d3.select("body").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.call(tip);
d3.json('http://localhost:3000/graphs/data', type, function(error, data) {
x.domain(data.map(function(d) { return d.route; }));
y.domain([0, d3.max(data, function(d) { return d.count; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Frequency");
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.route); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.count); })
.attr("height", function(d) { return height - y(d.count); })
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
});
function type(d) {
d.count = +d.count;
return d;
}
</script>
d3.json(), unlike d3.csv(), takes only two arguments, with the second being the callback function. Your call
d3.json('http://localhost:3000/graphs/data', type, function(error, data) {
passes the result of the call to type, not to the anonymous function after that, which is never executed. The call should be
d3.json('http://localhost:3000/graphs/data', function(error, data) {

JSON data structure for D3jS report and D3jS code

I am trying to achieve the below report from JSON data
var data = [{"MonthYearShortName":"2014-09-13T00:00:00","Product":"Deposits","Actual":330393232.5,"Forecast":495589848.75,"Target":495589848.75},{"MonthYearShortName":"2014-09-13T00:00:00","Product":"Fee Based","Actual":111868709.42,"Forecast":167803064.13,"Target":167803064.13},{"MonthYearShortName":"2014-09-13T00:00:00","Product":"Lending","Actual":18146873.33,"Forecast":27220309.995,"Target":27220309.995}]
I am not sure if this is the right data structure. If I am picking the wrong structure to create the report, some help would be great.
I am using the below code for generating the report.
<div id="ReportContent" runat="server" style="border: 1px solid #58595d; border: 1px solid rgba(88, 89, 93, .3);"><svg></svg></div>
function ChartCreate() {
var color = d3.scale.linear()
.domain([0, d3.max(data, function (d) { return d.Target; })]) //change
.range(["#f3c40e", "#7d6507"]);
var width = 420,
margin = 100, //add
barHeight = 20;
var x = d3.scale.linear()
.domain([0, d3.max(data, function(d) { return d.Actual; })]) //change
.range([0, width]);
var chart = d3.select('#ReportContent_ReportContent svg')
.attr("width", width + margin)
.attr("height", barHeight * data.length);
var bar = chart.selectAll("g")
.data(data, function(d) { return d.Actual; })
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; });
bar.append("rect")
.attr("width", function(d) { return x(d.Actual); }) //change
.attr("height", barHeight) //change
.attr("fill", function(d) { return color(d.Actual); }); //change
bar.append("text")
.attr("text-anchor", "start") //add
.attr("x", function(d) { return x(d.Actual); }) //change
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d) { return d.Product; });
}