How to update axis using d3.js - d3.js

I'm trying to display different data on a graph. The user can change the displayed data clicking on a radio button. I'm using a "Bubble chart" to render the data.
For each type of data I need to update the Yaxis (the domain is different).
Here is what I've done for now:
Chart initialisation
var svg = d3.select("body .main-content").append("svg")
.attr("class", "chart")
.attr("width", width)
.attr("height", height);
Initialise the Axis
initAxis();
function initAxis()
{
var y = d3.scale.linear().domain([0,1000]).range([height-margin, margin]).nice(),
x = d3.scale.linear().domain([0,23]).range([margin,width-margin]),
yAxis = d3.svg.axis().scale(y).orient("left"),
xAxis = d3.svg.axis().scale(x).orient("bottom");
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + margin + ",0)")
.call(yAxis);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height - margin) + ")")
.call(xAxis);
}
Update the chart
function update(type)
{
// Get the data
type = type || 'default';
var m = max[type],
mi = min[type]+0.1,
data = dataset[type],
step = stp[type];
// Set the functions
var y = d3.scale.linear().domain([mi,m]).range([height-margin, margin]).nice();
var o = d3.scale.linear().domain([0,m]).range([.5,1]);
var r = d3.scale.linear().domain([0,Math.sqrt(m)]).range([0,30]);
var x = d3.scale.linear().domain([0,23]).range([margin,width-margin]);
var color = function (a, b) {
for (var c = (a - 0) / (m - 0), d = [], e = 0; 3 > e; e++) d.push(Math.round(K[0][e] +
c * (K[1][e] - K[0][e])));
d.push(b || 0.7);
return "rgba(" + d.join(",") + ")"
}
//Attach the data to the graph
var circle = svg.selectAll("circle").data(data);
// Update existing element
circle.attr("class", "update");
// Add new element
circle.enter()
.append("circle")
.attr("class", "enter")
.attr("stroke-width", 0)
.attr("stroke", "black")
.transition()
.duration(750)
.attr("y", 0)
.style("fill-opacity", 1);
// Apply attribute to new and updated element
circle.attr("cx", function(d,i) {return x(d.h);})
.attr("cy", function(d,i) {return y(d.v);})
.attr("r", function(d,i) {return r(Math.sqrt(d.v));})
.style("fill", function(d,i) {return color(d.v);})
.style("opacity", function(d,i) {return o(d.v);})
.on("click", function(d,i){window.open(d.name,'_blank');})
.on("mouseover", function(d,i){d3.select(this).style("fill", "red").attr("stroke-width", 1);})
.on("mouseout", function(d,i){d3.select(this).style("fill", function(d,i) {return color(d.v);}).attr("stroke-width", 0);})
.append("title")
.text(function(d) { return d.v+' '+ d.t+' (adjusted) - '+ d.d })
.transition()
.duration(750)
.attr("y", 0)
.style("fill-opacity", 1);
// Remove old elements
circle.exit()
.attr("class", "exit")
.transition(750)
.ease("linear")
.attr("cy", 0)
.style("opacity", 0.2)
.remove();
// Update the Axis
var xAxis = d3.svg.axis().scale(x).orient("bottom");
var yAxis = d3.svg.axis().scale(y).orient("left");
svg.selectAll("g .y.axis")
.call(yAxis)
svg.selectAll("g .x.axis")
.call(xAxis);
}
The circles are updated correctly (transitions are not working tho) but the axis are not changing and I can't see why. I'm a bit lost, I've looked at many example but I cannot see what I'm doing wrong.
I'm using d3.js version: v3.1.10
Maxime

It looks like you are using the wrong selector while updating the axes:
svg.selectAll("g .y.axis")
.call(yAxis);
svg.selectAll("g .x.axis")
.call(xAxis);
maybe should read:
svg.selectAll("g.y.axis")
.call(yAxis);
svg.selectAll("g.x.axis")
.call(xAxis);

Why are you using "g .y.axis"?
Try:
svg.select(".y.axis")
.call(yAxis);
And similar for x axis.

Related

Update the colored area of a line chart

I create a line chart like that.
However, I added the possibility to update data. The "darker line" is updated correctly, the area no.
Here is a piece of code:
var margin = {top: 10, right: 10, bottom: 35, left: 30};
var width = 500 - margin.left - margin.right;
var height = 220 - margin.top - margin.bottom;
var x = d3.scalePoint().range([width, 0]);
var y = d3.scaleLinear().range([height, 0]);
x.domain([...new Set(dataFilter.map(function(d) {
return d.year;
}))]);
y.domain([minX, 100]);
var xAxis = d3.axisBottom(x);
var yAxis = d3.axisLeft(y);
var valueline = d3.line()
.x(function(d) {
return x(d.year);
})
.y(function(d) {
return y(d.euro);
})
.defined(function(d) {
return (d.euro !== 0 && !isNaN(d.euro));
});
var area = d3.area()
.x(function(d) {
return x(d.year);
})
.y0(function(d) {
return y(d.euro);
})
.y1(height)
.defined(function(d) {
return (d.euro !== 0 && !isNaN(d.euro));
});
var svg = d3.select("#chart")
.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.append("path")
.attr("class", "linePath")
.attr('fill', 'none')
.attr('stroke', 'steelblue')
.attr('stroke-width', 1)
.attr("d", valueline(dataFilter));
svg.append('path')
.datum(dataFilter)
.attr('d', area)
.attr('fill', 'steelblue')
.attr('stroke', 'none')
.attr('opacity', '0.1')
.attr('class', 'areaLines');
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', '.15em')
.attr('transform', 'rotate(-65)');
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
function updateData() {
dataFilter = ...; // other data
// Scale the range of the data again minX is now different
x.domain([...new Set(dataFilter.map(function(d) {
return d.year;
}))]);
y.domain([minX, 100]);
var svg = d3.select("#chart").transition();
svg.select(".linePath")
.duration(1000)
.attr("d", valueline(dataFilter));
svg.select(".x.axis")
.duration(1000)
.call(xAxis)
.selectAll('text')
.style('text-anchor', 'end')
.attr('dx', '-.8em')
.attr('dy', '.15em')
.attr('transform', 'rotate(-65)');
// update area (doesn't work): TypeError: svg.select(...).datum is not a function
svg.select('.areaLines')
.datum(dataFilter)
.attr('d', area)
.duration(1000);
svg.select(".y.axis")
.duration(1000)
.call(yAxis);
}
When I run it I get: TypeError: svg.select(...).datum is not a function.
Why?
I found this question but I'cant able to solve the problem. Thanks a lot!!
You cannot transition the datum, it makes no sense. That's why datum() is not a transformation method.
Instead of that, transition the d attribute:
svg.select('.areaLines')
.attr('d', area(dataFilter))
.duration(1000);

dataset created with d3.nest isn't drawing correctly

I am trying to visualize a dataset to see major players in the pangolin trade. I want each country to be part of a categorical scale on the y-axis, and the x-axis is the date, and I want each trade instance to be represented as a circle, with x being the date it happened, y being the position for that particular country, and r being the number of instances accumulated so far (represented in my data as r). Basically my data is from 2010 to 2016, and includes the country name where pangolins are either imported to or exported from, the count (accumulated trade instances up until this date), and the date (yyyy-mm-dd).
Below is part of my data, which I store in the variable trade:
[{"date":"2010-10-22","country":"Thailand","rank":4,"count":1},{"date":"2010-10-28","country":"Malaysia","rank":2,"count":1},{"date":"2010-11-8","country":"Thailand","rank":4,"count":2},{"date":"2010-11-18","country":"Nepal","rank":7,"count":1},{"date":"2010-11-22","country":"China","rank":5,"count":1},{"date":"2010-11-22","country":"China","rank":5,"count":2},{"date":"2010-11-27","country":"India","rank":1,"count":1},{"date":"2010-11-28","country":"India","rank":1,"count":2},{"date":"2010-11-28","country":"India","rank":1,"count":3},{"date":"2010-11-30","country":"India","rank":1,"count":4},{"date":"2010-12-17","country":"Malaysia","rank":2,"count":2},{"date":"2010-12-22","country":"Vietnam","rank":3,"count":1},{"date":"2011-01-3","country":"Nepal","rank":7,"count":2},{"date":"2011-02-12","country":"Myanmar","rank":8,"count":1},{"date":"2011-02-25","country":"Malaysia","rank":2,"count":3},{"date":"2011-02-26","country":"Malaysia","rank":2,"count":4},{"date":"2011-03-2","country":"South Africa","rank":18,"count":1},{"date":"2011-03-2","country":"Rwanda","rank":35,"count":1},{"date":"2011-03-2","country":"Mozambique","rank":22,"count":1},{"date":"2011-03-2","country":"Kenya","rank":12,"count":1},{"date":"2011-03-3","country":"China","rank":5,"count":3},{"date":"2011-02-21","country":"Vietnam","rank":3,"count":2},{"date":"2011-03-24","country":"Malaysia","rank":2,"count":5},{"date":"2011-04-4","country":"Malaysia","rank":2,"count":6},{"date":"2011-03-25","country":"India","rank":1,"count":5},{"date":"2011-03-26","country":"Malaysia","rank":2,"count":7},{"date":"2011-04-2","country":"Nepal","rank":7,"count":3},{"date":"2011-04-20","country":"Thailand","rank":4,"count":3},{"date":"2011-05-11","country":"China","rank":5,"count":4},{"date":"2011-05-11","country":"China","rank":5,"count":5},{"date":"2011-05-26","country":"Indonesia","rank":6,"count":1},{"date":"2011-05-26","country":"India","rank":1,"count":6},{"date":"2011-05-29","country":"Indonesia","rank":6,"count":2},{"date":"2011-06-6","country":"India","rank":1,"count":7},{"date":"2011-06-7","country":"Mozambique","rank":22,"count":2},{"date":"2011-06-5","country":"India","rank":1,"count":8},{"date":"2011-06-12","country":"Malaysia","rank":2,"count":8},{"date":"2011-06-13","country":"Singapore","rank":21,"count":1},{"date":"2011-06-14","country":"Malaysia","rank":2,"count":9},{"date":"2011-06-17","country":"India","rank":1,"count":9},{"date":"2011-06-19","country":"India","rank":1,"count":10},{"date":"2011-06-26","country":"Thailand","rank":4,"count":4},{"date":"2011-06-30","country":"India","rank":1,"count":11},{"date":"2011-07-4","country":"Malaysia","rank":2,"count":10},{"date":"2011-07-5","country":"Zimbabwe","rank":14,"count":1},{"date":"2011-07-12","country":"Indonesia","rank":6,"count":3},{"date":"2011-07-18","country":"Indonesia","rank":6,"count":4},{"date":"2011-07-27","country":"Nepal","rank":7,"count":4},{"date":"2011-08-16","country":"Nepal","rank":7,"count":5},{"date":"2011-08-19","country":"Namibia","rank":33,"count":1},{"date":"2011-08-23","country":"India","rank":1,"count":12},{"date":"2010-09-17","country":"Myanmar","rank":8,"count":2},{"date":"2011-09-1","country":"Zimbabwe","rank":14,"count":2},{"date":"2011-09-13","country":"Indonesia","rank":6,"count":5},{"date":"2011-09-13","country":"Malaysia","rank":2,"count":11},{"date":"2011-09-13","country":"Myanmar","rank":8,"count":3},{"date":"2011-09-21","country":"Malaysia","rank":2,"count":12},{"date":"2011-09-26","country":"Thailand","rank":4,"count":5},{"date":"2011-09-30","country":"Indonesia","rank":6,"count":6},{"date":"2011-10-1","country":"Sri Lanka","rank":19,"count":1},{"date":"2011-10-6","country":"India","rank":1,"count":13},{"date":"2011-10-7","country":"India","rank":1,"count":14},{"date":"2011-10-18","country":"Indonesia","rank":6,"count":7},{"date":"2011-10-18","country":"Indonesia","rank":6,"count":8},{"date":"2011-10-18","country":"Indonesia","rank":6,"count":9},{"date":"2011-10-22","country":"India","rank":1,"count":15},{"date":"2011-10-24","country":"India","rank":1,"count":16},{"date":"2011-11-28","country":"United States","rank":32,"count":1},{"date":"2011-12-15","country":"Vietnam","rank":3,"count":3},{"date":"2011-12-27","country":"Thailand","rank":4,"count":6},{"date":"2012-01-4","country":"Philippines","rank":15,"count":1},{"date":"2012-01-5","country":"Kenya","rank":12,"count":2},{"date":"2012-01-6","country":"Philippines","rank":15,"count":2},{"date":"2012-01-17","country":"Philippines","rank":15,"count":3},{"date":"2012-01-24","country":"China","rank":5,"count":6},{"date":"2012-02-22","country":"Malaysia","rank":2,"count":13},{"date":"2012-03-1","country":"Malaysia","rank":2,"count":14},{"date":"2012-03-19","country":"Pakistan","rank":11,"count":1},{"date":"2012-03-21","country":"Malaysia","rank":2,"count":15},{"date":"2012-03-23","country":"Vietnam","rank":3,"count":4},{"date":"2012-04-27","country":"Vietnam","rank":3,"count":5},{"date":"2012-04-23","country":"Belgium","rank":31,"count":1},{"date":"2012-06-7","country":"Thailand","rank":4,"count":7},{"date":"2012-06-7","country":"Thailand","rank":4,"count":8}];
and here is my code:
var margin = {left:120, top:20, right:0, bottom:50};
var width = 1000;
var height = 800;
var data=trade;
var tradeByCountry = d3.nest()
.key(function(d) { return d.country; })
.entries(trade);
console.log(tradeByCountry);
tradeByCountry.forEach(function(country){
country['number']=country.values.length;
console.log(country);
});
var country_colors = ["#393b79","#5254a3", '#6b6ecf', '#9c9ede', '#637939', '#8ca252','#b5cf6b','#cedb9c',
'#8c6d31','#bd9e39','#e7ba52','#e7cb94','#843c39','#ad494a','#d6616b','#e7969c','#7b4173','#a55194',
'#ce6dbd','#de9ed6', '#9467bd', '#c5b0d5','#3182bd', '#6baed6','#17becf','#9edae5','#e6550d','#fd8d3c','#fdae6b',
'#31a354','#74c476','#a1d99b','#d62728','#ff9896','#7f7f7f','#c7c7c7'];
var colors = d3.scale.ordinal()
.domain(d3.range(tradeByCountry.length))
.range(country_colors);
tradeByCountry.sort(function(x, y){
return d3.descending(x.number, y.number);
})
var countriesArray = [];
tradeByCountry.forEach(function(country){
countriesArray.push(country.key);
});
console.log(countriesArray);
var x = d3.time.scale()
.rangeRound([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var timeFormat = d3.time.format("%Y-%m-%d");
x.domain([timeFormat.parse('2010-10-22'),timeFormat.parse('2016-12-30')]);
y.domain(countriesArray);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
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.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("date");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "translate(35,-25)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("countries");
svg.selectAll(".dot")
.data(tradeByCountry)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 7)
.attr("cx", function(d) { return 0; })
.attr("cy", function(d,i) { return (height/tradeByCountry.length)*i; })
.style("fill", function(d,i) { return colors(i); });
svg.selectAll("text.labels")
.data(tradeByCountry)
.enter()
.append("text")
.text(function(d) {return d.key})
.attr("x", 0)
.attr("y", function(d,i) { return (height/tradeByCountry.length)*i; })
.attr("transform", "translate(-120,5)")
.attr("fill",function(d,i) { return colors(i); });
svg.selectAll('.line')
.data(tradeByCountry)
.enter().append('line')
.attr("x1", 0) // x position of the first end of the line
.attr("y1",function(d,i) { return (height/tradeByCountry.length)*i; })
.attr("x2", width) // x position of the second end of the line
.attr("y2", function(d,i) { return (height/tradeByCountry.length)*i; })
.style("stroke",function(d,i) { return colors(i); })
.attr("id", function(d){return d.key});
//PROBLEM HERE!!!!!!!!!!!
var g = svg
.selectAll("g")
.data(tradeByCountry)
.enter().append("g")
.selectAll(".dot")
.data(function(d) {return d.values;})
.enter().append("circle")
.attr("id", function(d){ return d.count;})
.attr("r", function(d){return d.count;})
.attr("cx", function(d,i) { console.log (d.date);return (x(timeFormat.parse(d.date))); })
.attr("cy", function(d,i) { return (height/tradeByCountry.length)*i; })
.style("fill", function(d,i) { return colors(i); });
I am having trouble specifically at the very last part of my code, where I can't get all the circles to draw and not in the correct r, as I would like r to increase as the trade accumulates over time for a country, instead it seems that r is different according to country:
Two things, firstly in your example .selectAll("g") at the point you mark as having the error was picking up g elements in the axes, so the first few countries weren't getting their data displayed. This doesn't appear to be the case in your screenshot but it was happening given the code you posted, so I just qualified those gs with the .country class.
The second thing, and what was causing your specific problem was this line:
.attr("cy", function(d,i) { return (height/tradeByCountry.length)*i; })
I'm guessing you thought the index variable i here was still tied to the tradeByCountry array, which it would have been after selectAll("g.country").data(tradebyCountry) but at this point we've now made a nested selection .selectAll(".dot") on d.values for each country's data so i is now indexing those list of values. So that line of code above will take the values for each country and separate them all vertically, always starting from the top row - when in fact you want them on the same line, just separated by country.
What you wanted (I = India, M = Malaysia, T = Thailand)
I--- I0 I1 I2
M--- M0M1 M2
T--- T0 T1 T2
What you were getting
I--- I0 M0 T0
M--- M1 I1 T1
T--- I2 T2 M2
This was also hidden by the fact .attr("fill") also had the same mistake so the colours on each row were consistent (I've used d.rank instead to fix it).
Solution 1: To make sure the values stay on the same correct line use i before you do the nested selection so it still refers to the countries like this, which will offset each g element by the correct amount:
.attr("transform", function(d,i) {
return "translate(0,"+(height/tradeByCountry.length)*i+")";
})
and simply set cy to be zero for everything you add to this g element and they'll all be in a straight line (and on the right line)
Full code at the PROBLEM HERE! stage:
var g = svg
.selectAll("g.country")
.data(tradeByCountry)
.enter().append("g")
.attr("class", "country")
.attr("transform", function(d,i) {
return "translate(0,"+(height/tradeByCountry.length)*i+")";
})
.selectAll(".dot")
.data(function(d) {return d.values;})
.enter().append("circle")
.attr("class", "dot")
.attr("id", function(d){ return d.country+"_"+d.date+"_"+d.count;})
.attr("r", function(d){ return d.count;})
.attr("cx", function(d,i) { console.log (d.date);return (x(timeFormat.parse(d.date))); })
.attr("cy", function(d,i) { return 0; })
.style("fill", function(d,i) { return colors(d.rank); });
http://jsfiddle.net/d4typ567/1/
Solution 2: It's also the case that d3 maintains a parent index variable for nested selections (usually denoted ii) that can be passed into most d3 .attr and .style functions, so you could do .attr("cy", function(d,i, ii) { return (height/tradeByCountry.length)*ii; }) instead, but offsetting the g element is only 1 operation whereas this is done for every circle. Remember to do the same for the color (fill) function.

misalignment in the ticks of axes and rectangles of bar graph in d3

I am using d3 js to draw a bar graph. I have x and y axis too.
The x axis would hold the 'names' and y axis the 'marks'. I am using ordinal scale for x axis.
In my json input dataset_rule_errors, I have 10 entries.
My code is
var svgd = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var x_domain = dataset_rule_errors.map(function(d) { return d.Rulename; })
var xScale = d3.scale.ordinal()
.domain(dataset_rule_errors.map(function (d) { return d.Rulename; }))
.rangeBands([padding_rule, wsvg]);
var xaxeScale = d3.scale.ordinal()
.domain(x_domain)
.rangePoints([padding_rule, wsvg]);
var xAxis = d3.svg.axis()
.scale(xaxeScale)
.tickValues(x_domain)
.orient("bottom");
//drawing rectangles
svgd.append("g")
.selectAll("rect") //based on the data in the dataset[] array, append rectangles s.t.
.data(dataset_rule_errors) //
.enter()
.append("rect")
.attr("x", function (d, i) {
return xScale(d.Rulename); // x position of rect as per i->0,1,2,3,...
})
.attr("y", function (d) {
return (h_rule - yScale(d.NumRuleFailed)); //y position of rect as per (h-value) to prevent inverted range
})
.attr("width", xScale.rangeBand())//"10") //depending upon domain->no of inputs - with of band is decided acc. to fit in svg
.attr("height", function (d) {
return yScale(d.NumRuleFailed); //depending upon domain->value of inputs - with of band is decided acc. to fit in svg
})
.attr("fill", function (d, i) { //colour based on values -> more errors - dark coloured bars
if(i%2==0)
return "rgb(" + 255 + "," + 255 + "," + 200 + ")";
else
return "rgb(" + 0 + "," + 0 + "," + 200 + ")";
})
.attr("stroke", "black");
//drawing x axis with ticks
svgd.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + 0 + "," + (h_rule) + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("text-anchor", "start")
.attr("transform", function (d) {
return "rotate(-90)"
})
.selectAll(".tick text")
.style("text-anchor", "start");
The problem I am facing is that my rectangles and the ticks of x-axis do not align with one another.
The reason is because I have 10 bars and therefore, I should be having 11 ticks including the one at the beginning and the end. But I have only 10 ticks, which distribute evenly along the axis length, so they do not coincide with the rectangle beginnings just like in this question Unable to align ticks with d3.js.
But the solution for this question did not work out for me. What can I do?
dataset_rule_errors = data I retrieve from my database
[{"Rulename":"A","NumRuleFailed":34321},{"Rulename":"B","NumRuleFailed":43},{"Rulename":"C","NumRuleFailed":45522},
{"Rulename":"D","NumRuleFailed":43643},{"Rulename":"E","NumRuleFailed":152},{"Rulename":"F","NumRuleFailed":152}]
I could not reproduce the issue you said you were having but I highly recommend using rangeRoundBands for a bar chart.
You can achieve the bar chart with the following setup:
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .2);
var y = d3.scale.linear()
.range([height, 0]);
// Finding domain of x (all our rulenames)
x.domain(data.map(function(d) {
return d.Rulename;
}));
// Finding domain of y (min and max values)
y.domain([d3.min(data, function(d) {
return d.NumRuleFailed;
}), d3.max(data, function(d) {
return d.NumRuleFailed;
})]);
var xAxis = d3.svg.axis()
.scale(x)
// no need yo specify ticks, x scale
// will take care of that
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
And the following for axis and rect rendering:
// Render xAxis
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", "-.50em")
.attr("text-anchor", "start")
.attr("transform", "rotate(-90)")
.selectAll(".tick text")
.style("text-anchor", "start")
// Render yAxis
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("NumRuleFailed");
// Render rects
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.Rulename);
})
.attr("width", x.rangeBand())
.attr("y", function(d) {
return y(d.NumRuleFailed);
})
.attr("fill", function(d, i) { //colour based on values -> more errors - dark coloured bars
return (i % 2) ? 'green' : 'red';
})
.attr("height", function(d) {
return height - y(d.NumRuleFailed);
});
Full Plnkr: https://plnkr.co/edit/jmtMGcRyT9hM5efwwTOb?p=preview

Placement of .transition for lines in d3?

I'm looking to get a transition animation into my line graph, but I'm not really sure where the .transition() would go. I tried to put it in where I thought it should go, but that just froze the graph. Here's my code:
var vis = d3.select('#visual'),
WIDTH = 1000,
HEIGHT = 500,
MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
},
xRange = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(lineData, function(d) {
return d.x;
}), d3.max(lineData, function(d) {
return d.x;
})]),
yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(lineData, function(d) {
return d.y - 1;
}), d3.max(lineData, function(d) {
return d.y;
})]),
//setup x
xAxis = d3.svg.axis()
.scale(xRange)
.tickSize(5)
.tickSubdivide(true),
//setup y
yAxis = d3.svg.axis()
.scale(yRange)
.tickSize(5)
.orient("left")
.tickSubdivide(true);
vis.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
.call(xAxis);
vis.append("svg:g")
.attr("class", "y axis")
.attr("transform", "translate(" + (MARGINS.left) + ",0)")
.call(yAxis);
var lineFunc = d3.svg.line()
.x(function(d) {
return xRange(d.x);
})
.y(function(d) {
return yRange(d.y);
});
vis.append("svg:path")
.attr("class", "myLine")
.attr("d", lineFunc(lineData))
.attr("stroke", "blue")
.attr("stroke-width", 2)
.attr("fill", "none");
// lineFunc.transition(); <--Where I thought the tag should be
// lineFunc.exit().transition()
// .remove();
And here's the whole thing if necessary: https://jsfiddle.net/hppkqfy7/
Transitions in D3 usually apply to attribute(s) and .transition() should be called before setting the new value of the attribute(s). This will tell D3 to interpolate between old and new.
In your case, you'd call .transition() just before setting the updated d attribute:
d3.select(".myLine")
.transition()
.attr("d", lineFunc(lineData));
Complete demo here.

order displayed before my labels in D3

I am new to programming and new to D3, I am learning it using the book "Getting started with D3" and all the examples I can find around the internet.
To start practicing I am trying to create a column chart but am encountering two problems with my x-label:
The labels displayed below my x-axis are not in line with the columns. To be precise, I have numbers displayed before the labels start being displayed.
I am wondering how to rotate the labels. When I try the rotate attribute all of the x-axis is being rotated and I would only like to rotate the labels. I have found some questions related to this but haven't completely understood the answers.
My data are formatted this way:
{"Low_Income_Household_Internet_access":
[{"Country":"Chile","Value":9.69},
{"Country":"New Zealand","Value":47.8},
{"Country":"Greece","Value":25.39},
{"Country":"Italy","Value":33.26},
{"Country":"Israel","Value":40.31},
{"Country":"Portugal","Value":22.72},
{"Country":"United Kingdom","Value":56},...
],
"High_Income_Household_Internet_access":
[{"Country":"Chile","Value":59.78701735},
{"Country":"New Zealand","Value":78.3},
{"Country":"Greece","Value":81.14},
{"Country":"Italy","Value":84.44},
{"Country":"Israel","Value":86.59},
{"Country":"Portugal","Value":89.73},
{"Country":"United Kingdom","Value":90},...
]}
and my code is the following:
function draw(data) {
"use strict";
var w = 600;
var h = 300;
var barPadding = 3;
var margin=20;
var format = d3.format(",.0f");
var x = d3.scale.ordinal().rangeBands([0, w-margin], .1),
y = d3.scale.linear().range([h-margin, margin]);
var xAxis = d3.svg.axis().scale(x).orient("top").tickSize(0),
yAxis = d3.svg.axis().scale(y).orient("left").tickSize(-w);
var svg = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h)
.append("g")
.attr("transform", "translate(" + margin + ",0)");
// Set the scale domain.
x.domain(d3.range(data.Low_Income_Household_Internet_access.length));
y.domain([0, d3.max(data.Low_Income_Household_Internet_access,function(d) { return d.Value; }) ]);
var bar = svg.selectAll("g.bar")
.data(data.Low_Income_Household_Internet_access)
.enter().append("g")
.attr("class", "bar")
.attr("transform", function(d) { return "translate(" + x(d.Country)+ "," + y(d.Value) + " ) "; });
bar.append("rect")
.attr("width", x.rangeBand())
.attr("height", function(d) { return h-margin- y(d.Value); })
.on("mouseover",function(d) {
d3.select(this)
.style("fill","red")
})
.on("mouseout",function(d) {
d3.select(this)
.style("fill","grey")
})
.append("svg:title")
.text(function(d) { return "" + d.Country + ": " + d.Value + " %"; });
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0, 295)")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);}

Resources