How can I add label to a bar chart? The bar chart extends along the x-axis and I want to append the labels along the y-axis.
I read some examples and they use an external .tsv or .csv file. Can I store them in an array instead? My code is below :
var data = [7, 8, 15, 16];
var label = ["as","bs","cs","ds"];
var width = 420,
barHeight = 20;
var x = d3.scale.linear()
.domain([0, d3.max(data)])
.range([0, width]);
var chart = d3.select(".chart")
.attr("width", width)
.attr("height", barHeight * data.length);
var bar = chart.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; });
bar.append("rect")
.attr("width", x)
.attr("height", barHeight - 1);
bar.append("text")
.attr("x", function(d) { return x(d) - 3; })
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d) { return d; });
You can get the value of your label by the index like this :
bar.append("text")
.attr("x", function(d) { return x(d) - 3; })
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d, i) { return label[i]; });
Related
I created a simple barchart with d3.js. My problem my complete chart is not shown but it is cut off to the right. Only 16 of the 20 bars are shown
I guess it is a scaling issue but I don't know how to fix it. If I increase the width it shows me more bars, but I'd like to keep the original width. Here is my code:
{#Creating a barchart#}
var dataset = [133,131,111,345,665,665,454,44,4,235....]; //These are the bars
var svgWidth = 900, svgHeight = 400, barPadding = 10;
var barWidth = (svgWidth / dataset.length * 2 );
var svg = d3.select('svg')
.attr("width", svgWidth)
.attr("height", svgHeight);
var yScale = d3.scaleLinear()
.domain([0, d3.max(dataset)])
.range([0, svgHeight]);
var barChart = svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("y", function(d) {
return svgHeight - yScale(d)
})
.attr("height", function(d) {
return yScale(d);
})
.attr("width", barWidth - barPadding)
.attr("transform", function (d, i) {
var translate = [barWidth * i, 0];
return "translate("+ translate +")";
});
var text = svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return d;
})
.attr("y", function(d, i) {
return svgHeight - d - 2;
})
.attr("x", function(d, i) {
return barWidth * i;
})
.attr("fill", "black");
</script>
Any help is highly appreciated!! Thanks in advance!
Try removing the multiplication by 2 in your barWidth formula
var barWidth = svgWidth / dataset.length;
I want to modify the basic side bar chart to be a stack bar chart, which will reflect partial-amount:total relationship. I already created a matrix with the following:
[{y:0, x0:221, x1:1670},
{y:1, x0:581, x1:1473},
{y:2, x0:2485, x1:2643},
{y:3, x0:135, x1:8714},
{y:4, x0:31, x1:211}]
For reference, in each case the true total would be x0 + x1.
I have a normal bar chart for the totals, but I cannot understand how to convert it to a stacked chart. Also, if there is a way to accomplish this without mutating the data (subtracting x0 from the true total to get x1), that would also be ideal.
Existing BarChart
// Constants
var width = 450,
barHeight = 20,
height = 300,
padding = 10,
leftMargin = 10;
var typeBarChart = d3.select('.typeBarChart')
.attr('width', width)
.attr('height', barHeight*dataGroupByType.length); // dataGroupByType is a D3 nest data series with length is 5
// X-axis;
var x = d3.scale.linear()
.domain([0, maxCrime]) // maxCrime determine elsewhere, approx. 8850
.range([0, width]);
var chart = d3.select(".typeBarChart")
.attr("width", width)
.attr("height", barHeight * dataGroupByType.length);
var bar = chart.selectAll("g")
.data(dataGroupByType)
.enter()
.append("g")
.attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; });
bar.append("rect")
.attr("width", function(d) { return x(d.values); })
.attr("height", barHeight - 1);
bar.append("text")
.attr("x", function(d) {
if (d.values < 1000) {
return x(d.values) + 20;
} else {
return x(d.values) - 3;
}
})
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d) { return d.values; });
There are a some issues with the code template....
I refined few to create a simplest stacked bar graph.. this would help you get started...
Working fiddle: https://jsfiddle.net/egmf47ne/
CODE:
HTML
<div class ="typeBarChart"></div>
JS
var _data = [{y:0, x0:221, x1:1670},
{y:1, x0:581, x1:1473},
{y:2, x0:2485, x1:2643},
{y:3, x0:135, x1:8714},
{y:4, x0:31, x1:211}]
// Constants
var width = 450,
barHeight = 20,
height = 300,
padding = 10,
leftMargin = 10;
var typeBarChart = d3.select('.typeBarChart')
.append('svg')
.attr('width', width)
.attr('height', barHeight*_data.length);
var x = d3.scale.linear()
.domain([0, 8850]) // maxCrime
.range([0, width]);
var bar = typeBarChart.selectAll("g")
.data(_data)
.enter()
.append("g")
.attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; });
bar.append("rect")
.attr("fill","blue") // blue bars of x0 + x1
.attr("width", function(d) { return x(d.x0 + d.x1); })
.attr("height", barHeight - 1);
bar.append("rect")
.attr("fill","red") // red bars of x0 only
.attr("width", function(d) { return x(d.x0); })
.attr("height", barHeight - 1);
i want a vertical stacked bar chart with x axis and y axis labels and tool tip showing values and legends. please show me how to reduce the size of the graph also....
Now bar stacked bar chart is showing with very big size But no x and y axis... amd tool tip and legends is also not coming...
var w = 700,
h = 500;
var margin = {top: 25, right: 75, bottom: 85, left: 85};
// create canvas
var svg = d3.select("#bar-chart").append("svg:svg")
.attr("class", "chart")
.attr("width", w)
.attr("height", h )
.append("svg:g")
.attr("transform", "translate(10,470)");
x = d3.scale.ordinal().rangeRoundBands([0, w-50]);
y = d3.scale.linear().range([0, h-50]);
z = d3.scale.ordinal().range(["yellow", "grey", "orange"]);
var colors = [["Cat 980", "#D0D0D0"],
["Kom500", "#4DAF4A"],
["Kom501", "#D0D0D0"],
["Kom502", "#D0D0D0"]];
console.log("RAW MATRIX---------------------------");
// 4 columns: ID,c1,c2,c3
var matrix = [
[ 1, 5871, 8916, 2868],
[ 2, 10048, 2060, 6171],
[ 3, 16145, 8090, 8045],
[ 4, 990, 940, 6907]
];
console.log(matrix);
console.log("REMAP---------------------------");
var remapped =["c1","c2","c3"].map(function(dat,i){
return matrix.map(function(d,ii){
return {x: ii, y: d[i+1] };
});
});
console.log(remapped);
console.log("LAYOUT---------------------------");
var stacked = d3.layout.stack()(remapped);
console.log(stacked);
var xScale = d3.scale.ordinal().domain(d3.range(stacked.length)).rangeRoundBands([0, w], 0.05);
// ternary operator to determine if global or local has a larger scale
var yScale = d3.scale.linear().domain([0, d3.max(remapped)]).range([h, 0]);
var xAxis = d3.svg.axis().scale(xScale).tickFormat(function(d) { return stacked[d].keyword; }).orient("bottom");
var yAxis = d3.svg.axis().scale(yScale).orient("left").ticks(5);
x.domain(stacked[0].map(function(d) { return d.x; }));
y.domain([0, d3.max(stacked[stacked.length - 1], function(d) { return d.y0 + d.y; })]);
// show the domains of the scales
console.log("x.domain(): " + x.domain())
console.log("y.domain(): " + y.domain())
console.log("------------------------------------------------------------------");
// Add a group for each column.
var valgroup = svg.selectAll("g.valgroup")
.data(stacked)
.enter().append("svg:g")
.attr("class", "valgroup")
.style("fill", function(d, i) { return z(i); })
.style("stroke", function(d, i) { return d3.rgb(z(i)).darker(); });
// xAxis
svg.append("g") // Add the X Axis
.attr("class", "x axis")
.attr("transform", "translate(0," + (h) + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", function(d) {
return "rotate(-25)";
})
;
// yAxis
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(0 ,0)")
.call(yAxis)
;
// xAxis label
svg.append("text")
.attr("transform", "translate(" + (w / 2) + " ," + (h + margin.bottom - 5) +")")
.style("text-anchor", "middle")
.text("Keyword");
//yAxis label
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x", 0 - (h / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Product");
// Add a rect for each date.
var rect = valgroup.selectAll("rect")
.data(function(d){return d;})
.enter().append("svg:rect")
.attr("x", function(d) { return x(d.x); })
.attr("y", function(d) { return -y(d.y0) - y(d.y); })
.attr("height", function(d) { return y(d.y); })
.attr("width", x.rangeBand());
// add legend
var legend = svg.append("g")
.attr("class", "legend")
.attr("transform", "translate(70,10)")
;
var legendRect = legend.selectAll('rect').data(colors);
legendRect.enter()
.append("rect")
.attr("x", w - 65)
.attr("y", 0) // use this to flip horizontal
.attr("width", 10)
.attr("height", 10)
.attr("y", function(d, i) {
return i * 20;
})
// .attr("x", function(d, i){return w - 65 - i * 70}) // use this to flip horizontal
.style("fill", function(d) {
return d[1];
});
var legendText = legend.selectAll('text').data(colors);
legendText.enter()
.append("text")
.attr("x", w - 52)
.attr("y", function(d, i) {
return i * 20 + 9;
})
.text(function(d) {
return d[0];
});
svg.select("g.x").call(xAxis);
svg.select("g.y").call(yAxis);
I use the tutorial from http://bost.ocks.org/mike/bar/3/. While I want to have a grouped bar chart like
(source: academyhealth.org)
.Followed the answer of my last question, i create two data sets but the y-position of the second data sets can never be set as same as the first one. Here is code snippet that set position of bar chart.
var bar = chart.selectAll("g")
.data(data_1)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(" + (i * barWidth+60) + ", -100)"; });
Here is the code:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.chart rect {
fill: steelblue;
}
.chart text {
fill: white;
font: 10px sans-serif;
text-anchor: middle;
}
</style>
<svg class="chart"></svg>
<svg class="chart_1"></svg>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var data = [4, 5];
var width = 960,
height = 500;
var y = d3.scale.linear()
.range([height, 0])
.domain([0, d3.max(data)]);
var chart = d3.select(".chart")
.attr("width", width)
.attr("height", height);
var barWidth_ = width /data.length;
var barWidth = barWidth_/2;
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); })
.attr("height", function(d) { return height - y(d); })
.attr("width", barWidth -200);
bar.append("text")
.attr("x", barWidth / 2)
.attr("y", function(d) { return y(d) + 3; })
.attr("dy", ".75em")
.text(function(d) { return d; });
var data_1 = [1000, 1000];
var width = 960,
height = 500;
var y = d3.scale.linear()
.range([height, 0])
.domain([0, d3.max(data_1)]);
var chart = d3.select(".chart_1")
.attr("width", width)
.attr("height", height);
var barWidth_ = width /data_1.length;
var barWidth = barWidth_/2;
var bar = chart.selectAll("g")
.data(data_1)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(" + (i * barWidth+60) + ", -100)"; });
bar.append("rect")
.attr("y", function(d) { return y(d); })
.attr("height", function(d) { return height - y(d); })
.attr("width", barWidth -200);
bar.append("text")
.attr("x", barWidth / 2)
.attr("y", function(d) { return y(d) + 3; })
.attr("dy", ".75em")
.text(function(d) { return d; });
</script>
Here is the jsfiddle code here
http://jsfiddle.net/tw981/BDLt6/
I'm new to d3.js and am trying to create my own two-sided bar-chart. The chart it is based on is http://jasonneylon.wordpress.com/2013/09/05/two-sided-horizontal-barchart-using-d3-js/
I keep coming up with a blank screen whenever I run it, and am unsure as to what I am doing wrong.
var names = [];
var total = [];
var otherValue = [];
d3.text("results.csv",function(data){
var data = d3.csv.parseRows(data);
for( var a = 1;a <data.length;a++){
var names.push(data[a][0]);
var total.push(parseFloat(data[a][1]));
var otherValue.push(parseFloat(data[a][2]));
}
var labelArea = 160;
var chart,
width = 400,
bar_height = 20,
height = bar_height * (data.length);
var rightOffset = width + labelArea;
var chart = d3.select("body")
.append('svg')
.attr('class', 'chart')
.attr('width', labelArea + width + width)
.attr('height', height);
var xFrom = d3.scale.linear()
.domain([0, d3.max(otherValue)])
.range([0, width]);
var y = d3.scale.ordinal()
.domain(names)
.rangeBands([10, height]);
var yPosByIndex = function(d, index){ return y(index); }
chart.selectAll("rect.left")
.data(otherValue)
.enter().append("rect")
.attr("x", function(pos) { return width - xFrom(pos); })
.attr("y", yPosByIndex)
.attr("class", "left")
.attr("width", xFrom)
.attr("height", y.rangeBand());
chart.selectAll("text.leftscore")
.data(otherValue)
.enter().append("text")
.attr("x", function(d) { return width - xFrom(d); })
.attr("y", function(d, z){ return y(z) + y.rangeBand()/2; } )
.attr("dx", "20")
.attr("dy", ".36em")
.attr("text-anchor", "end")
.attr('class', 'leftscore')
.text(String);
chart.selectAll("text.name")
.data(names)
.enter().append("text")
.attr("x", (labelArea / 2) + width)
.attr("y", function(d){ return y(d) + y.rangeBand()/2; } )
.attr("dy", ".20em")
.attr("text-anchor", "middle")
.attr('class', 'name')
.text(String);
var xTo = d3.scale.linear()
.domain([0, d3.max(total)])
.range([0, width]);
chart.selectAll("rect.right")
.data(total)
.enter().append("rect")
.attr("x", rightOffset)
.attr("y", yPosByIndex)
.attr("class", "right")
.attr("width", xTo)
.attr("height", y.rangeBand());
});
chart.selectAll("text.score")
.data(total)
.enter().append("text")
.attr("x", function(d) { return xTo(d) + rightOffset; })
.attr("y", function(d,z){ return y(z) + y.rangeBand()/2; } )
.attr("dx", -5)
.attr("dy", ".36em")
.attr("text-anchor", "end")
.attr('class', 'score')
.text(String);
});
</script>
Using the 3 arrays was a different idea I tried after not managing to figure it out from anything i had found so far.
The csv file looks like this:
ABC,140,35
DEF,164,45
GHI,89,15
JKL,56,20
MNO,20,31
Thanks for any help