D3 barchart not populating. - javascript

I am trying to create a bar-chart using D3. However, the bar chart is not populating. The following is my code:
var data = [Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random()]
var height = 900
var width = 600
var x = d3.scale.linear()
.range([0, width])
.domain([0, d3.max(data)])
var y = d3.scale.linear()
.range([height, 0])
.domain([0, 500])
var svg = d3.select(".barchart").append('svg')
.attr("height", height)
.attr("width", width)
var rect = svg.selectAll('rects')
.data(data)
.enter()
.append('rects')
.attr("height", function(d, i) { return height - y(d) })
.attr("width", function (d, i) { return x(d) })
.attr("x", function(d, i) { return x(i) })
.attr("y", function(d, i) { return y(d) })
.attr("fill", "blue")

There is more than one issue so I'll just list them out.
Changes to your x and y scales. Yours were a bit off.
var x = d3.scale.linear()
.range([0, width])
.domain([0, data.length]);
var y = d3.scale.linear()
.range([0, height])
.domain([0, d3.max(data)]);
Change 'rects' to 'rect'.
var rect = svg.selectAll('rect') // <-- here
.data(data)
.enter()
.append('rect') // <-- and here
Lastly the logic for your x, y, width, and height calculations were off.
.attr("height", function(d, i) { return y(d); })
.attr("width", width / data.length - 1)
.attr("x", function(d, i) { return x(i); })
.attr("y", function(d, i) { return height - y(d); })
Make sure you are using semicolons.
http://jsfiddle.net/gnouvg6z/

Related

d3 linkHorizontal for straight line curves

Can d3 linkHorizontal be used for straight line curves? If not, am I missing any d3 feature for that kind of link path? Of-course I can always go manual and calculate it myself.
From
To
You could use d3.curveStep, which creates a path with right-angle corners:
var link = d3.line()
.x(function(d,i) { return xScale(i); })
.y(function(d,i) { return yScale(d); })
.curve(d3.curveStep);
var width = 500
var height = 500
var margin = 25
var data = [
[3, 7]
]
var xScale = d3.scaleLinear()
.domain([0, 1])
.range([0, width])
var yScale = d3.scaleLinear()
.domain([0, 10])
.range([height, 0])
var svg = d3.select("body").append("svg")
.attr("width", width + margin + margin)
.attr("height", height + margin + margin)
var g = svg.append("g")
.attr("transform", "translate(" + margin + "," + margin + ")")
var points = g.selectAll("g")
.data(data)
.enter()
.append("g")
points.append("path")
.datum(d => d)
.attr("d", link)
.style("stroke", "black")
.style("fill", "none")
points.selectAll("circle")
.data(d => d)
.enter()
.append("circle")
.attr("cx", (d,i) => xScale(i))
.attr("cy", (d) => yScale(d))
.attr("r", 5)
.style("stroke", "none")
.style("fill", "black")
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

How to scale y-Axis in d3.js according to data input correctly

I created a small Barchart. My problem is that the y-axis doesn't scale according to my dataset. Here is a screenshot:
So as you can see the 313 is a little bit above the 800 scale. I would like the 300 to be at the 300. I tweaked with the scalings but I just end up messing it up completely. I am very new to D3.js so I hope someone can help.
Here is my code:
var svgWidth = 1000, svgHeight = 800;
var barWidth = svgWidth / month_description.length;
var barPadding = 5;
var svg = d3.select('svg')
.attr("width", svgWidth)
.attr("height", svgHeight);
var barChart = svg.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("y", function(d) {
return svgHeight - d - 20
})
.attr("x", function(d, i) {
return i + 10;
})
.attr("height", function(d) {
return d;
})
.attr("width", barWidth - barPadding)
.attr("class", "bar")
.attr("transform", function (d, i) {
var translate = [barWidth * i, 0];
return "translate("+ translate +")";
});
var text = svg.selectAll("text")
.data(data)
.enter()
.append("text")
.text(function(d) {
return d;
})
.attr("y", function(d, i) {
return svgHeight - 20;
})
.attr("x", function(d, i) {
return barWidth * i + 35;
})
.attr("fill", "white");
var xScale = d3.scaleLinear()
.domain([0, d3.max(month_description)])
.range([0, svgWidth]);
var yScale = d3.scaleLinear()
.domain([0, d3.max(data)])
.range([svgHeight, 0]);
var x_axis = d3.axisBottom()
.scale(xScale);
var y_axis = d3.axisLeft()
.scale(yScale);
svg.append("g")
.attr("transform", "translate(50, 10)")
.call(y_axis);
var xAxisTranslate = svgHeight - 20;
svg.append("g")
.attr("transform", "translate(50, " + xAxisTranslate +")")
.call(x_axis);
Help is very much appreciated. Thanks very much in advance!!

turn Y axis upside down

I've created a simple bar chart in D3, but the the bars are being created from top to bottom, instead of bottom to top. Below is the xScale, yScale and bar generation code:
var xscale = d3.scale.linear()
.domain([0, data.length])
.range([0, 240]);
var yscale = d3.scale.linear()
.domain([0, 100])
.range([0, 240]);
var bar = canvas.append('g')
.attr("id", "bar-group")
.attr("transform", "translate(10,20)")
.selectAll('rect')
.data(data)
.enter()
.append('rect')
.attr("class", "bar")
.attr("height", function(d, i) {
return yscale(d);
})
.attr("width", 15)
.attr("x", function(i) {
return yscale(i);
})
.attr("y", 0)
.style("fill", function(i) {
return colors(i);
});
Tried to swap yScale ranges but no success. Here is the fiddle.
In the SVG coordinates system, the origin (0,0) is at the top left corner, not the bottom left corner.
Besides that, your SVG has only 150px heigh. Thus, change your scale:
var yscale = d3.scale.linear()
.domain([0, 100])
.range([0, 150]);
And the math of your bars:
.attr("height", function(d, i) {
return yscale(d);
})
.attr("y", function(d){
return 150 - yscale(d)
})
Here is your updated fiddle: https://jsfiddle.net/bga2q72f/
PS: don't use the same scale for the x and y positions. It's quite confusing.

D3 spaces between groups

How do I add some padding between groups in a grouped bar chart?
I have 2 groups and 5 categories on the x axis. Im trying to get some padding between the pairs ([group1, group2,] space, [group1, group2], etc.) I tried with rangeBand(), with the scale, etc. but its not working.
Any suggestions?
jsfiddle
Relevant samples of the code:
var values = feature.properties;
var data = [
{name:"NoDipOL",value:values["NoDipOL"]},
{name:"NoDipNOL",value:values["NoDipNOL"]},
{name:"HSOL",value:values["HSOL"]},
{name:"HSNOL",value:values["HSNOL"]},
{name:"ColOL",value:values["ColOL"]},
{name:"ColNOL",value:values["ColNOL"]},
{name:"UnOL",value:values["UnOL"]},
{name:"UnNOL",value:values["UnNOL"]}
];
var Colors = ["#a6cee3", "#1f78b4"];
var ColorNames = ["Group1", "Group2"];
[...]
// Scale for x and y axis
var x = d3.scale.ordinal()
.domain(["No diploma", "High school", "College", "University"])
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.domain([0, d3.max(data, function(d){return d.value;})])
.range([height, 0]);
//Ordinal x axis.
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.outerTickSize(0);
[...]
bar.append("rect")
.attr("x", function(d, i) { return i * barWidth;})
.attr("width", barWidth - 1 )
.attr("y", function(d) {return y(d.value); })
.attr("height", function(d) {return height - y(d.value);})
.attr("fill", function(d, i) { return Colors[i % 2]; }); //Alternate colors
bar.append("text")
.attr("class", "text")
.text(function(d) { return d.value; })
.attr("y", function(d) {return y(d.value) - 5; })
.attr("x", function(d, i) { return i * barWidth;})
.attr("dx", barWidth / 2)
.attr("fill", "black")
.attr("font-family", "sans-serif")
.attr("font-size", "14px")
.attr("text-anchor", "middle");
You use the rangeBand to place your ticks but you don't use it to size and place your rects. First fix the data so it can use the rangeBand:
var data = [
{name:"No diploma",value:values["NoDipOL"]},
{name:"No diploma",value:values["NoDipNOL"]},
{name:"High school",value:values["HSOL"]},
{name:"High school",value:values["HSNOL"]},
{name:"College",value:values["ColOL"]},
{name:"College",value:values["ColNOL"]},
{name:"University",value:values["UnOL"]},
{name:"University",value:values["UnNOL"]}
];
Then place your rects:
bar.append("rect")
.attr("x", function(d, i) {
return (i % 2 === 0) ? // every other bar
x(d.name) : // if even place at start of band
x(d.name) + x.rangeBand()/2; // if odd (second bar) move it over
})
.attr("width", x.rangeBand()/2 ) // and width is half the rangeband
...
Updated example.

D3 the x axis positions in wrong way

I have run into problem of displaying the chart X axis which is translated in wrong position. Here is my example http://jsfiddle.net/staar2/Vww3h/1/.
As you can look from the html inspector the svg elements get translated wrong. What I think the xScale are set wrong.
var data = JSON.parse('[{"hour":0,"time":147},{"hour":1,"time":0},{"hour":2,"time":74},{"hour":3,"time":141},{"hour":4,"time":137},{"hour":5,"time":210},{"hour":6,"time":71},{"hour":7,"time":73},{"hour":8,"time":0},{"hour":9,"time":68},{"hour":10,"time":70},{"hour":11,"time":0},{"hour":12,"time":147},{"hour":13,"time":0},{"hour":14,"time":0},{"hour":15,"time":69},{"hour":16,"time":67},{"hour":17,"time":67},{"hour":18,"time":66},{"hour":19,"time":0},{"hour":20,"time":0},{"hour":21,"time":66},{"hour":22,"time":210},{"hour":23,"time":0}] ');
var w = 15,
h = 80;
var xScale = d3.scale.linear()
.domain([0, 1])
.range([0, w]);
var yScale = d3.scale.linear()
.domain([0, d3.max(data, function (d) {
return d.time;
})])
.rangeRound([5, h]);
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(5);
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left");
var chart = d3.select("#viz")
.append("svg")
.attr("class", "chart")
.attr("width", w * data.length - 1)
.attr("height", h);
chart.selectAll("rect")
.data(data)
.enter().append("rect")
.attr("x", function(d, i) {
return xScale(i) - 0.5;
})
.attr("y", function(d) {
return h - yScale(d.time) - 0.5;
})
.attr("width", w)
.attr("height", function(d) {
return yScale(d.time);
});
chart.selectAll("text")
.data(data)
.enter()
.append("text")
.text(function(d) {
if (d.time > 10) {
return Math.round(d.time);
}
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "#FFF")
.attr("text-anchor", "middle")
.attr("x", function(d, i) {
return xScale(i) + w / 2;
})
.attr("y", function(d) {
return h - yScale(d.time) - 0.5 + 10;
});
chart.append("g")
.attr("transform", "translate(0," + (h) + ")")
.call(xAxis);
You need to change your xScale domain and range as well accordingly, as
xScale
.domain([0, data.length-1])
.range([0, w*(data.length-1)])
while you call xScale(i) where i is the index of data element, as far as i understood, and so the domain should be between 0 - data.length.

Categories