d3 Focus + Context via Brushing not displaying anything - javascript

i am trying to visualize some data using Focus + Context via brushing using D3. I am having some problems with the data. I have just changed the data fetch lines of code since i am fetching 2 values using d3.json. Here is my code -
<script type="text/javascript">
var margin = {top: 10, right: 10, bottom: 100, left: 40},
margin2 = {top: 430, right: 10, bottom: 20, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
height2 = 500 - margin2.top - margin2.bottom;
var parseDate = d3.time.format("%a %e %H %M").parse;
var x = d3.time.scale().range([0, width]),
x2 = d3.time.scale().range([0, width]),
y = d3.scale.linear().range([height, 0]),
y2 = d3.scale.linear().range([height2, 0]);
var xAxis = d3.svg.axis().scale(x).orient("bottom"),
xAxis2 = d3.svg.axis().scale(x2).orient("bottom"),
yAxis = d3.svg.axis().scale(y).orient("left");
var brush = d3.svg.brush()
.x(x2)
.on("brush", brushed);
var area = d3.svg.area()
.interpolate("monotone")
.x(function(d) { return x(d.receiveddate); })
.y0(height)
.y1(function(d) { return y(d.gtse); });
var area2 = d3.svg.area()
.interpolate("monotone")
.x(function(d) { return x2(d.receiveddate); })
.y0(height2)
.y1(function(d) { return y2(d.gtse); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
d3.json("rest.php/lastweek"+"/"+"dibya", function(error, data) {
var allData = data.records;
allData.forEach(function(d) {
var formattedDate = new Date(+d.receiveddate).toString();
d.receiveddate = parseDate(d3.time.format("%a %e %H %M")(new Date(formattedDate)));
d.gtse = +d.gtse;
});
x.domain(d3.extent(allData.map(function(d) { return d.receiveddate; })));
y.domain([0, d3.max(allData.map(function(d) { return d.gtse; }))]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("path")
.datum(data)
.attr("clip-path", "url(#clip)")
.attr("d", area);
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "y axis")
.call(yAxis);
context.append("path")
.datum(data)
.attr("d", area2);
context.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", -6)
.attr("height", height2 + 7);
});
function brushed() {
x.domain(brush.empty() ? x2.domain() : brush.extent());
focus.select("path").attr("d", area);
focus.select(".x.axis").call(xAxis);
}
Here the received date is fetched as date in Millis and converted accordingly. The received date is in the frequency of 10 mins. The browser loads the x and y axes according to the values passed but no graph is plotted. Neither do i get any error in console. What am i missing?

Related

Build d3 line chart based on javascript json variable

Edited: added zooming.
I'm getting data from php function (just sql request) to js variable, so js variable is json data. I need to build zoomable d3 line chart based on this json.
Json variable looks like this:
[{temp: "5", created_at: "2017-03-19"},
{temp: "5", created_at: "2017-03-19"},
{temp: "26", created_at: "2018-04-20"}]
Error is: Error: <path> attribute d: Expected number, "MNaN,NaNLNaN,NaNL…"
Line_chart.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line); ///One error is on this line
context.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line2); ///Second error is on this line
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 110, left: 40},
margin2 = {top: 430, right: 20, bottom: 30, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
height2 = +svg.attr("height") - margin2.top - margin2.bottom;
var parseDate = d3.timeParse("%Y-%M-%D");
var x = d3.scaleTime().range([0, width]),
x2 = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
y2 = d3.scaleLinear().range([height2, 0]);
var xAxis = d3.axisBottom(x),
xAxis2 = d3.axisBottom(x2),
yAxis = d3.axisLeft(y);
var brush = d3.brushX()
.extent([[0, 0], [width, height2]])
.on("brush end", brushed);
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
var line = d3.line()
.x(function (d) { return x(d.Date); })
.y(function (d) { return y(d.Air_Temp); });
var line2 = d3.line()
.x(function (d) { return x2(d.Date); })
.y(function (d) { return y2(d.Air_Temp); });
var clip = svg.append("defs").append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("width", width)
.attr("height", height)
.attr("x", 0)
.attr("y", 0);
var Line_chart = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("clip-path", "url(#clip)");
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
var data = jsonfile
x.domain(d3.extent(data, function(d) { return d.created_at; }));
y.domain([0, d3.max(data, function (d) { return d.temp; })]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "axis axis--y")
.call(yAxis);
Line_chart.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
context.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line2);
context.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
console.log(data);
function brushed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
var s = d3.event.selection || x2.range();
x.domain(s.map(x2.invert, x2));
Line_chart.select(".line").attr("d", line);
focus.select(".axis--x").call(xAxis);
svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
.scale(width / (s[1] - s[0]))
.translate(-s[0], 0));
}
function zoomed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush
var t = d3.event.transform;
x.domain(t.rescaleX(x2).domain());
Line_chart.select(".line").attr("d", line);
focus.select(".axis--x").call(xAxis);
context.select(".brush").call(brush.move, x.range().map(t.invertX, t));
}
function type(d) {
d.Date = parseDate(d.created_at);
d.Air_Temp = +d.temp;
return d;
}
jsonfile in d3.json is this json variable.
I have problem with dislaying data. I have x and y axis but no displayed data.
---------Reason of the error is incorrectly parsed data, still don't know where code goes wrong.-----------
I added: after var data = jsonfile
data.forEach(function(d){
d.created_at = parseDate(d.created_at);
d.temp = +d.temp;
});
And it worked. Graph builds using console. Don't why and where json strings parsed incorrectly.

d3 passing data through mouseover event

I have a chart that on mouseover gives me the data i am looking for
.on("mouseover", function(d) {
givegraph(this.__data__);
})
This passes the correct data i am looking for. My data looks like this for one item on a mouseover event
{
color: "red",
uses : 22,
years_used:[1,2,3,4,5],
numberofPens:[44,39,29,54,09]
}
My givegraph function looks like
function givegraph(d){
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 300 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
var valueline = d3.svg.line()
.x(function(d) {return x(d.years_used); })
.y(function(d) { return y(d.numberofpens); });
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 + ")");
x.domain(d3.extent(data, function(d) { return d.years_used; }));
y.domain([0, d3.max(data, function(d) { return d.numberofpens; })]);
svg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
}
The data is not being pass through when I call it in the valueline or domain functions. When i use the command to see the data in the console, nothing shows.
.x(function(d) {console.log(d);return x(d.years_used); })
The data is being pass through in the givegraph function but when i use it for the anonymous function it is not there. How can i fix this

Plotting a line graph along with Bar graph in d3js. Issue with Date

I'm learning d3js using various examples found online.
I've been trying to plot a chart with dual Y axis and an X-axis. The Y axis on the left side would plot a bar chart against the X-axis and the Y-axis on the right side would plot a line chart against X-axis. The Bar graph plots as exactly as required but the line graph does not. The X-axis is date (2015-10-15 04:10). Following this example.
The code I wrote
var margin = {top: 50, right: 50, bottom: 100, left: 50},
width = 900 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.time.format("%m/%d/%Y %H:%M:%S").parse;
var x = d3.scale.ordinal().rangeRoundBands([0, width], .05);
var yTxnVol = d3.scale.linear().range([height, 0]);
var yResTime = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
var yAxis = d3.svg.axis()
.scale(yTxnVol)
.orient("left")
var yAxis2 = d3.svg.axis()
.scale(yResTime)
.orient("right")
.ticks(10);
var svg = d3.selectAll("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 + ")");
d3.csv("../res/data.csv", function(error, data) {
data.forEach(function(d) {
d.AVRG_RESP_TIME = +d.AVRG_RESP_TIME;
d.TXN_VOL = +d.TXN_VOL;
});
x.domain(data.map(function(d) { return d.TYM; }));
yTxnVol.domain([0, d3.max(data, function(d) { return d.TXN_VOL+50; })]);
yResTime.domain([0, d3.max(data, function(d) { return d.AVRG_RESP_TIME+50; })]);
var minDate = d3.min(data, function(d){return d.TYM});
var maxDate = d3.max(data, function(d){ return d.TYM});
var xScale = d3.time.scale().range([0,width]);//.domain([minDate, maxDate]);
xScale.domain(d3.extent(data, function(d) { return new Date(d.TYM); }));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-90)" );
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
svg.append("g")
.attr("class","y axis")
.attr("transform","translate("+width+ ", 0)")
.call(yAxis2)
svg.selectAll("bar")
.data(data)
.enter().append("rect")
.attr("class", "yhover")
.attr("x", function(d) { return x(d.TYM); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return yTxnVol(d.TXN_VOL); })
.attr("height", function(d) { return height - yTxnVol(d.TXN_VOL); })
var line = d3.svg.line()
.x(function(d) { return xScale(new Date(d.TYM));})
.y(function(d) { return d.AVRG_RESP_TIME; });
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
});
The Output Trying to make this to a meaningful line graph. Got NaN error while formatting the dates.
Could someone help me to make this a proper line graph ?
The csv data sample
TYM, AVRG_RESP_TIME, TXN_VOL
2015-10-15 04:00:00, 12, 170
2015-10-15 04:10:00, 18, 220
2015-10-15 04:20:00, 28, 251
2015-10-15 05:00:00, 19, 100
First, fix your csv file. It is improperly formatted and should not have spaces after the comma.
Second, You are trying to mix an ordinal scale and a time scale for you xAxis. This isn't going to work. For your use case, just stick with time.
Here's a reworking of your code with explanatory comments:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3#3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>
<body>
<script>
var margin = {
top: 50,
right: 50,
bottom: 100,
left: 50
},
width = 900 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse;
// x scale should be time and only time
var x = d3.time.scale().range([0, width]);
var yTxnVol = d3.scale.linear().range([height, 0]);
var yResTime = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
var yAxis = d3.svg.axis()
.scale(yTxnVol)
.orient("left")
var yAxis2 = d3.svg.axis()
.scale(yResTime)
.orient("right")
.ticks(10);
var svg = d3.selectAll("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 + ")");
//d3.csv("data.csv", function(error, data) {
var data = [{"TYM":"2015-10-15 04:00:00","AVRG_RESP_TIME":"12","TXN_VOL":"170"},{"TYM":"2015-10-15 04:10:00","AVRG_RESP_TIME":"18","TXN_VOL":"220"},{"TYM":"2015-10-15 04:20:00","AVRG_RESP_TIME":"28","TXN_VOL":"251"},{"TYM":"2015-10-15 05:00:00","AVRG_RESP_TIME":"19","TXN_VOL":"100"}];
// just make TYM a date and keep it as a date
data.forEach(function(d) {
d.TYM = parseDate(d.TYM);
d.AVRG_RESP_TIME = +d.AVRG_RESP_TIME;
d.TXN_VOL = +d.TXN_VOL;
});
// get our min and max date in milliseconds
// set a padding around our domain of 15%
var minDate = d3.min(data, function(d){
return d.TYM;
}).getTime();
var maxDate = d3.max(data, function(d){
return d.TYM;
}).getTime();
var padDate = (maxDate - minDate) * .15;
x.domain([new Date(minDate - padDate), new Date(maxDate + padDate)]);
yTxnVol.domain([0, d3.max(data, function(d) {
return d.TXN_VOL + 50;
})]);
yResTime.domain([0, d3.max(data, function(d) {
return d.AVRG_RESP_TIME + 50;
})]);
// set an intelligent bar width
var barWidth = (width / x.ticks().length) - 20;
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-90)");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + width + ", 0)")
.call(yAxis2)
svg.selectAll("bar")
.data(data)
.enter().append("rect")
.attr("class", "yhover")
.attr("x", function(d) {
// center bar on time
return x(d.TYM) - (barWidth / 2);
})
.attr("width", barWidth)
.attr("y", function(d) {
return yTxnVol(d.TXN_VOL);
})
.attr("height", function(d) {
return height - yTxnVol(d.TXN_VOL);
})
.style("fill","orange");
var line = d3.svg.line()
.x(function(d) {
return x(d.TYM);
})
.y(function(d) {
return d.AVRG_RESP_TIME;
});
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line)
.style("fill","none")
.style("stroke","steelblue")
.style("stoke-width","3px");
// });
</script>
</body>
</html>
The issue with the line graph filling with black was due to improper css. The new css property.
.line {
fill: none;
stroke: darkgreen;
stroke-width: 2.5px;
}
For the dates I formatted it to (%Y-%m-%d %H:%M) format and it worked.

D3js Zoom lines and points from csv file won't work for points

I'm trying to modify Zoomable area from http://bl.ocks.org/mbostock/4015254 with adding data points from csv file in it, but couldn't get things right. Only lines can be zoomed and moved but not points.
My guess is I need to put circle's .attr("transform", function(d){ return "translate("+x(d[key0])+","+y(d[key1])+")";}); within function draw, but then it cannot recognize key0 and key1 (I have multiple columns in the csv file).
The following is the code I modified. Any idea how to fix this?
<script>
var margin = {top: 20, right: 60, bottom: 30, left: 20},
width = 960 - margin.left - margin.right,
height = 800 - margin.top - margin.bottom;`
var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse,
formatDate = d3.time.format("%Y");
var x = d3.time.scale()
.range([0, width]);
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("right")
.tickSize(-width)
.tickPadding(6);
var xGrid = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickSize(-height,0)
.ticks(5)
.tickPadding(1)
.tickFormat("");
var line = d3.svg.line();
var zoom = d3.behavior.zoom()
.scaleExtent([1,128])
.on("zoom", draw);
var zoom2 = d3.behavior.zoom()
.scaleExtent([1,128])
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 + ")")
.call(zoom);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + width + ",0)");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height/2 + ")");
svg.append("g")
.attr("class", "x line")
.attr("transform", "translate(0," + height/2 + ")")
.append("svg:line")
.attr("x1",x(0))
.attr("y1",-y(0))
.attr("x2",x(width))
.attr("y2",-y(0));
svg.append("g")
.attr("class", "grid")
.attr("transform", "translate(0,"+ height + ")");
svg.append("path")
.attr("class", "line");
svg.append("rect")
.attr("class", "pane")
.attr("width", width)
.attr("height", height);
circle = svg.selectAll("circle");
d3.csv("encounter.csv", function(error, data) {
key0 = Object.keys(data[0])[1];
key1 = Object.keys(data[0])[3];
data.forEach(function(d,i) {
d[key0] = parseDate(d[key0]);
d[key1] = +d[key1];
});
x.domain([new Date(2014, 0, 1), new Date(2015, 0, 1)]);
y.domain(d3.extent(data, function(d){return d[key1];})).nice();
zoom.x(x);
svg.select("path.line").data([data]);
line.x(function(d) { return x(d[key0]); })
.y(function(d) { return y(d[key1]); });
circle.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 5)
.attr("transform", function(d){ return "translate("+x(d[key0])+","+y(d[key1])+")";});
draw();
});
function draw() {
svg.select("g.x.axis").call(xAxis);
svg.select("g.y.axis").call(yAxis);
svg.select("g.grid").call(xGrid);
svg.select("path.line").attr("d", line);
}

d3.js stacked chart plugin

Trying to develop a stacked chart plugin.
This was the basic version
http://jsfiddle.net/NYEaX/131/
this is my current plugin
http://jsfiddle.net/NYEaX/149/
_ there are issues though with a) having more than one chart b) updating the chart(s)
I've tried breaking up the code required to build the chart and update it/handle the block/morphs. I think I need to add transitions - enter/exit/remove on the code responsible for adding the stacked chart blocks.
buildChart: function(data, w, h, yLabel){
var that = this;
var margin = {top: 30, right: 55, bottom: (h * 0.56), left: 95},
width = w - margin.left - margin.right,
height = h - margin.top - margin.bottom;
this.x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
this.y = d3.scale.linear()
.rangeRound([height, 0]);
var colorArray = ["#538ed5", "#953735", "#e46d0a", "#75923c", "#b2a1c7", "#dc143c", "#87cefa", "#90ee90", "#add8e6", "#d3d3d3", "#cf1256", "#12cf5e"];
this.color = d3.scale.ordinal()
.range(colorArray);
var xAxis = d3.svg.axis()
.scale(this.x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(this.y)
.orient("left")
//.tickFormat(d3.format(".2s"));
var chartWidth = parseInt(width + margin.left + margin.right,10);
var chartHeight = parseInt(height + margin.top + margin.bottom,10);
var svg = d3.select(methods.el["selector"])
.append("svg")
.attr("class", "stackedchart")
.attr("width", chartWidth)
.attr("height", chartHeight)
.attr('viewBox', "0 0 "+chartWidth+" "+chartHeight)
.attr('perserveAspectRatio', "xMinYMid")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
this.color.domain(d3.keys(data[0]).filter(function(key) { return key !== "Label"; }));
data.forEach(function(d) {
var y0 = 0;
d.blocks = that.color.domain().map(function(name) {
return {name: name, values: d[name], y0: y0, y1: y0 += +d[name]};
});
d.total = d.blocks[d.blocks.length - 1].y1;
});
this.x.domain(data.map(function(d) { return d.Label; }));
this.y.domain([0, d3.max(data, function(d) { return d.total; })]);
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", "-3.5em")
.style("text-anchor", "end")
.text(yLabel);
var xlabels = svg.selectAll(".x.axis text")
.attr("transform", "rotate(-60) translate(-10,-10)")
that.manageStack(svg, data);
that.buildLegend();
//that.resizeChart();
}

Categories

Resources