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.
I am trying to populate a data set into D3's Bar chart data. I am using this example from the d3: http://bl.ocks.org/mbostock/3885304
Here is my sample data:
var data = [{"name":"0","members_count":4},{"name":"1","members_count":1},{"name":"2","members_count":6},{"name":"3","members_count":1},{"name":"4","members_count":1},{"name":"5","members_count":2},{"name":"6","members_count":4},{"name":"7","members_count":3},{"name":"8","members_count":5},{"name":"9","members_count":1},{"name":"10","members_count":2},{"name":"11","members_count":3},{"name":"12","members_count":2},{"name":"13","members_count":0},{"name":"14","members_count":5},{"name":"15","members_count":2},{"name":"16","members_count":2},{"name":"17","members_count":4},{"name":"18","members_count":2},{"name":"19","members_count":4},{"name":"20","members_count":3},{"name":"21","members_count":5},{"name":"22","members_count":8},{"name":"23","members_count":3},{"name":"24","members_count":2},{"name":"25","members_count":3},{"name":"26","members_count":4},{"name":"27","members_count":4},{"name":"28","members_count":1},{"name":"29","members_count":1},{"name":"30","members_count":3},{"name":"31","members_count":5},{"name":"32","members_count":4},{"name":"33","members_count":3},{"name":"34","members_count":6},{"name":"35","members_count":2},{"name":"36","members_count":2},{"name":"37","members_count":7},{"name":"38","members_count":2},{"name":"39","members_count":4},{"name":"40","members_count":2},{"name":"41","members_count":1},{"name":"42","members_count":8},{"name":"43","members_count":10},{"name":"44","members_count":1},{"name":"45","members_count":5},{"name":"46","members_count":2},{"name":"47","members_count":5},{"name":"48","members_count":3},{"name":"49","members_count":1},{"name":"50","members_count":9},{"name":"51","members_count":3},{"name":"52","members_count":2},{"name":"53","members_count":8},{"name":"54","members_count":2},{"name":"55","members_count":3},{"name":"56","members_count":2},{"name":"57","members_count":2},{"name":"58","members_count":5},{"name":"59","members_count":1},{"name":"60","members_count":2},{"name":"61","members_count":4},{"name":"62","members_count":2},{"name":"63","members_count":2},{"name":"64","members_count":6},{"name":"65","members_count":6},{"name":"66","members_count":1},{"name":"67","members_count":1},{"name":"68","members_count":3},{"name":"69","members_count":5},{"name":"70","members_count":3},{"name":"71","members_count":4},{"name":"72","members_count":4},{"name":"73","members_count":1},{"name":"74","members_count":3},{"name":"75","members_count":2},{"name":"76","members_count":4},{"name":"77","members_count":5},{"name":"78","members_count":2},{"name":"79","members_count":1},{"name":"80","members_count":2},{"name":"81","members_count":1},{"name":"82","members_count":4},{"name":"83","members_count":3},{"name":"84","members_count":1},{"name":"85","members_count":4},{"name":"86","members_count":1},{"name":"87","members_count":3},{"name":"88","members_count":1},{"name":"89","members_count":8},{"name":"90","members_count":6},{"name":"91","members_count":6},{"name":"92","members_count":3},{"name":"93","members_count":4},{"name":"94","members_count":5},{"name":"95","members_count":2},{"name":"96","members_count":3},{"name":"97","members_count":2},{"name":"98","members_count":3},{"name":"99","members_count":6},{"name":"100","members_count":3},{"name":"101","members_count":1},{"name":"102","members_count":0},{"name":"103","members_count":5},{"name":"104","members_count":2},{"name":"105","members_count":1},{"name":"106","members_count":7},{"name":"107","members_count":1},{"name":"108","members_count":1},{"name":"109","members_count":7},{"name":"110","members_count":5},{"name":"111","members_count":5},{"name":"112","members_count":2},{"name":"113","members_count":6},{"name":"114","members_count":1},{"name":"115","members_count":2},{"name":"116","members_count":1},{"name":"117","members_count":1},{"name":"118","members_count":10},{"name":"119","members_count":2},{"name":"120","members_count":6},{"name":"121","members_count":1},{"name":"122","members_count":1},{"name":"123","members_count":2},{"name":"124","members_count":4},{"name":"125","members_count":5},{"name":"126","members_count":1},{"name":"127","members_count":1},{"name":"128","members_count":1},{"name":"129","members_count":3},{"name":"130","members_count":3},{"name":"131","members_count":3},{"name":"132","members_count":4},{"name":"133","members_count":3},{"name":"134","members_count":1},{"name":"135","members_count":5},{"name":"136","members_count":5},{"name":"137","members_count":1},{"name":"138","members_count":2},{"name":"139","members_count":5},{"name":"140","members_count":1},{"name":"141","members_count":1},{"name":"142","members_count":2},{"name":"143","members_count":2},{"name":"144","members_count":4},{"name":"145","members_count":4},{"name":"146","members_count":3},{"name":"147","members_count":5},{"name":"148","members_count":2},{"name":"149","members_count":1},{"name":"150","members_count":2},{"name":"151","members_count":3},{"name":"152","members_count":0},{"name":"153","members_count":3},{"name":"154","members_count":1},{"name":"155","members_count":2},{"name":"156","members_count":2},{"name":"157","members_count":1},{"name":"158","members_count":5},{"name":"159","members_count":4},{"name":"160","members_count":4},{"name":"161","members_count":5},{"name":"162","members_count":4},{"name":"163","members_count":2},{"name":"164","members_count":4},{"name":"165","members_count":2},{"name":"166","members_count":2},{"name":"167","members_count":1},{"name":"168","members_count":1},{"name":"169","members_count":10},{"name":"170","members_count":4},{"name":"171","members_count":2},{"name":"172","members_count":2},{"name":"173","members_count":1},{"name":"174","members_count":5},{"name":"175","members_count":1},{"name":"176","members_count":1},{"name":"177","members_count":5},{"name":"178","members_count":3},{"name":"179","members_count":1},{"name":"180","members_count":5},{"name":"181","members_count":8},{"name":"182","members_count":4},{"name":"183","members_count":2},{"name":"184","members_count":1},{"name":"185","members_count":3},{"name":"186","members_count":1},{"name":"187","members_count":3},{"name":"188","members_count":1},{"name":"189","members_count":1},{"name":"190","members_count":6},{"name":"191","members_count":4},{"name":"192","members_count":5},{"name":"193","members_count":1},{"name":"194","members_count":4},{"name":"195","members_count":2},{"name":"196","members_count":2},{"name":"197","members_count":2},{"name":"198","members_count":0},{"name":"199","members_count":3},{"name":"200","members_count":3},{"name":"201","members_count":1},{"name":"202","members_count":1},{"name":"203","members_count":1},{"name":"204","members_count":5},{"name":"205","members_count":1},{"name":"206","members_count":1},{"name":"207","members_count":1},{"name":"208","members_count":1},{"name":"209","members_count":1},{"name":"210","members_count":5},{"name":"211","members_count":2},{"name":"212","members_count":1},{"name":"213","members_count":5},{"name":"214","members_count":1},{"name":"215","members_count":3},{"name":"216","members_count":1},{"name":"217","members_count":1},{"name":"218","members_count":4},{"name":"219","members_count":2},{"name":"220","members_count":1},{"name":"221","members_count":3},{"name":"222","members_count":1},{"name":"223","members_count":3},{"name":"224","members_count":1},{"name":"225","members_count":2},{"name":"226","members_count":1},{"name":"227","members_count":1},{"name":"228","members_count":11},{"name":"229","members_count":9},{"name":"230","members_count":9},{"name":"231","members_count":9},{"name":"232","members_count":10},{"name":"233","members_count":10},{"name":"234","members_count":10},{"name":"235","members_count":9},{"name":"236","members_count":10},{"name":"237","members_count":10},{"name":"238","members_count":10},{"name":"239","members_count":10},{"name":"240","members_count":9},{"name":"241","members_count":9},{"name":"242","members_count":9},{"name":"243","members_count":10},{"name":"244","members_count":10},{"name":"245","members_count":9},{"name":"246","members_count":2},{"name":"247","members_count":1},{"name":"248","members_count":2},{"name":"249","members_count":2},{"name":"250","members_count":1},{"name":"251","members_count":2},{"name":"252","members_count":1},{"name":"253","members_count":5},{"name":"254","members_count":1},{"name":"255","members_count":1},{"name":"256","members_count":1},{"name":"257","members_count":1},{"name":"258","members_count":1},{"name":"259","members_count":1},{"name":"260","members_count":2},{"name":"261","members_count":1},{"name":"262","members_count":1},{"name":"263","members_count":2},{"name":"264","members_count":1},{"name":"265","members_count":1},{"name":"266","members_count":1},{"name":"267","members_count":1},{"name":"268","members_count":2},{"name":"269","members_count":2},{"name":"270","members_count":1},{"name":"271","members_count":1},{"name":"272","members_count":0},{"name":"273","members_count":2},{"name":"274","members_count":1},{"name":"275","members_count":2},{"name":"276","members_count":2},{"name":"277","members_count":1},{"name":"278","members_count":3},{"name":"279","members_count":1},{"name":"280","members_count":1},{"name":"281","members_count":1},{"name":"282","members_count":1},{"name":"283","members_count":1},{"name":"284","members_count":1},{"name":"285","members_count":1},{"name":"286","members_count":1},{"name":"287","members_count":1},{"name":"288","members_count":1},{"name":"289","members_count":1},{"name":"290","members_count":1},{"name":"291","members_count":1},{"name":"292","members_count":1},{"name":"293","members_count":1},{"name":"294","members_count":1},{"name":"295","members_count":1},{"name":"296","members_count":1},{"name":"297","members_count":2},{"name":"298","members_count":2},{"name":"299","members_count":1},{"name":"300","members_count":1},{"name":"301","members_count":1},{"name":"302","members_count":1},{"name":"303","members_count":1},{"name":"304","members_count":1},{"name":"305","members_count":1},{"name":"306","members_count":1},{"name":"307","members_count":1},{"name":"308","members_count":1},{"name":"309","members_count":1},{"name":"310","members_count":1},{"name":"311","members_count":1},{"name":"312","members_count":1},{"name":"313","members_count":0},{"name":"314","members_count":1}]
This is chart's drawing code.
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = (960 - margin.left - margin.right) * data.length/50,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.domain([0,1])
.rangeRoundBands([0, width], 0.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")
.ticks(10, "%");
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(data.map(function(d) { return d.name; }));
y.domain([0, d3.max(data, function(d) { return d.members_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("fill","green")
.attr("x", function(d) { return x(d.name); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.members_count); })
.attr("height", function(d) { return height - y(d.members_count); });
This issue I am getting is that I have some white space which looks ugly. This space come before the 1st bar and also after the last bar of the chart. I have tried tweaking the x value of the bar, But I think that is not a good way to do.
This space does not come when the data set is small. But when dataset is large then this space comes up. How can I remove this space from the start and from end.
The problem is with this line in scale:
.rangeRoundBands([0, width], 0.1);
When there is not specified the third parameter outerPadding it adds before and after the chart extra space produced by the padding parameter for each bar. You have set the padding to 0.1. To solve this problem set the outerPadding parameter:
var x = d3.scale.ordinal()
.domain([0,1])
.rangeRoundBands([0, width], 0.1, 0);
Here is updated your code: http://jsfiddle.net/ojntup1a/