Related
I want to generate heat-map using d3.js by using csv data. For heat-map plotting I'm trying to set x-axis,y-axis and z-axis. But I'm facing issues while setting x-axis of the graph.
sample csv data :
var csv_data = "date,bucket,count\n07:31:01 001,10000,12\n07:31:01 119,50000,13\n07:31:01 128,60000,53\n07:31:01 200,90000,24\n07:31:01 555,75000,56";
program code-
<script>
var margin = {top: 20, right: 90, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y-%m-%d").parse,
formatDate = d3.time.format("%b %d");
//
var x = d3.time.scale().range([0, width]),
y = d3.scale.linear().range([height, 0]),
z = d3.scale.linear().range(["white", "steelblue"]);
// The size of the buckets in the CSV data file.
// This could be inferred from the data if it weren't sparse.
var xStep = 864e5,
yStep = 100;
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 + ")");
var csv_data = "date,bucket,count\n07:31:01 001,10000,12 005\n07:31:01 119,50000,13\n07:31:01 128,60000,53";
var buckets = d3.csv.parse(csv_data);
buckets.forEach(function(d) {
d.date = d.date;
d.bucket = +d.bucket;
d.count = +d.count;
});
x.domain(d3.extent(buckets, function(d) { return d.date; }));
y.domain(d3.extent(buckets, function(d) { return d.bucket; }));
z.domain([0, d3.max(buckets, function(d) { return d.count; })]);
// Extend the x- and y-domain to fit the last bucket.
// For example, the y-bucket 3200 corresponds to values [3200, 3300].
x.domain([x.domain()[0], +x.domain()[1] + xStep]);
y.domain([y.domain()[0], y.domain()[1] + yStep]);
// Display the tiles for each non-zero bucket.
svg.selectAll(".tile")
.data(buckets)
.enter().append("rect")
.attr("class", "tile")
.attr("x", function(d) { return x(d.date); })
.attr("y", function(d) { return y(d.bucket + yStep); })
.attr("width", x(xStep) - x(0))
.attr("height", y(0) - y(yStep))
.style("fill", function(d) { return z(d.count); });
// Add a legend for the color values.
var legend = svg.selectAll(".legend")
.data(z.ticks(6).slice(1).reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(" + (width + 20) + "," + (20 + i * 20) + ")"; });
legend.append("rect")
.attr("width", 20)
.attr("height", 20)
.style("fill", z);
legend.append("text")
.attr("x", 26)
.attr("y", 10)
.attr("dy", ".35em")
.text(String);
svg.append("text")
.attr("class", "label")
.attr("x", width + 20)
.attr("y", 10)
.attr("dy", ".35em")
.text("Count");
// Add an x-axis with label.
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.svg.axis().scale(x).orient("bottom"))
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.attr("text-anchor", "end")
.text("Time");
// Add a y-axis with label.
svg.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"))
.append("text")
.attr("class", "label")
.attr("y", 6)
.attr("dy", ".71em")
.attr("text-anchor", "end")
.attr("transform", "rotate(-90)")
.text("Latency");
</script>
Currently Graph is showing like this :
How I can set x-axis of graph with data whatever into the string? what I'm missing here?
The x axis represents a time scale. You need to pass in valid date objects instead of strings. In your particular example, this would become:
buckets.forEach(function(d) {
d.date = timeFormat.parse(d.date);
d.bucket = +d.bucket;
d.count = +d.count;
});
where timeFormat is a d3.time.format formatter:
var timeFormat = d3.time.format('%H:%M:%S %L');
To parse milliseconds you can use the following directive:
%L - milliseconds as a decimal number [000, 999].
In your CSV data, the dates should follow the specified format. for ex:
07:31:01 001,10000,12005
13:34:01 119,50000,13
17:39:01 128,60000,53
Here is a working jsfiddle:
I am trying to create a grouped bar chart using D3.js. I have followed the examples provided in the D3 wiki at GitHub and have a semi working graph. However, it seems like all datapoints for a certain value get plotted at the same spot.
my data looks is a JSON array, which looks like this
[{"experiment":30385,"c":1,"ratio":0.022,"stdev":0.363,"median":0.032,"zscore":6.359},
{"experiment":30385,"c":2,"ratio":-0.02,"stdev":0.351,"median":-0.005,"zscore":-4.786},
{"experiment":30385,"c":3,"ratio":0.074,"stdev":0.339,"median":0.089,"zscore":29.036},
{"experiment":30385,"c":4,"ratio":-0.077,"stdev":0.361,"median":-0.065,"zscore":-25.704},
{"experiment":30385,"c":5,"ratio":-0.354,"stdev":0.569,"median":-0.223,"zscore":-145.625},
{"experiment":30385,"c":6,"ratio":-0.02,"stdev":0.352,"median":-0.007,"zscore":-2.545},
{"experiment":30385,"c":7,"ratio":0.018,"stdev":0.346,"median":0.036,"zscore":7.412},
{"experiment":30385,"c":8,"ratio":-0.11,"stdev":0.348,"median":-0.096,"zscore":-37.69},
{"experiment":30385,"c":9,"ratio":-0.012,"stdev":0.357,"median":0.008,"zscore":-4.394},
{"experiment":30385,"c":10,"ratio":-0.054,"stdev":0.366,"median":-0.036,"zscore":-14.158},
{"experiment":30385,"c":11,"ratio":-0.071,"stdev":0.344,"median":-0.044,"zscore":-21.4},
{"experiment":30385,"c":12,"ratio":-0.01,"stdev":0.352,"median":0.002,"zscore":-1.467},
{"experiment":30385,"c":13,"ratio":-0.03,"stdev":0.366,"median":-0.014,"zscore":-2.375},
{"experiment":30385,"c":14,"ratio":-0.039,"stdev":0.339,"median":-0.025,"zscore":-8.816},
{"experiment":30385,"c":15,"ratio":-0.02,"stdev":0.357,"median":0.0065,"zscore":-4.2},
{"experiment":30385,"c":16,"ratio":0.449,"stdev":0.439,"median":0.4215,"zscore":69.859},
{"experiment":30385,"c":17,"ratio":-0.028,"stdev":0.367,"median":-0.007,"zscore":-4.9},
{"experiment":30385,"c":18,"ratio":-0.071,"stdev":0.357,"median":-0.061,"zscore":-17.268},
{"experiment":30385,"c":19,"ratio":0.143,"stdev":0.356,"median":0.1415,"zscore":13.961},
{"experiment":30385,"c":20,"ratio":0.022,"stdev":0.349,"median":0.0405,"zscore":3.462},
{"experiment":30385,"c":21,"ratio":-0.076,"stdev":0.335,"median":-0.086,"zscore":-11.368},
{"experiment":30385,"c":22,"ratio":0.038,"stdev":0.355,"median":0.07,"zscore":3.152},
{"experiment":30385,"c":23,"ratio":0,"stdev":0,"median":0,"zscore":3.152},
{"experiment":30385,"c":24,"ratio":0,"stdev":0,"median":0,"zscore":3.152},
{"experiment":30384,"c":1,"ratio":-0.058,"stdev":0.403,"median":-0.042,"zscore":-14.154},
{"experiment":30384,"c":2,"ratio":-1.017,"stdev":0.418,"median":-0.982,"zscore":-360.857},
{"experiment":30384,"c":3,"ratio":-0.094,"stdev":0.417,"median":-0.074,"zscore":-30.964},
{"experiment":30384,"c":4,"ratio":-0.155,"stdev":0.397,"median":-0.157,"zscore":-54.593},
{"experiment":30384,"c":5,"ratio":-0.024,"stdev":0.381,"median":-0.001,"zscore":-8.125},
{"experiment":30384,"c":6,"ratio":0.013,"stdev":0.37,"median":0.0245,"zscore":7.455},
{"experiment":30384,"c":7,"ratio":-0.2,"stdev":0.434,"median":-0.171,"zscore":-56.706},
{"experiment":30384,"c":8,"ratio":-0.017,"stdev":0.367,"median":0.003,"zscore":-5.621},
{"experiment":30384,"c":9,"ratio":0.025,"stdev":0.365,"median":0.044,"zscore":6.818},
{"experiment":30384,"c":10,"ratio":-0.168,"stdev":0.422,"median":-0.121,"zscore":-44.158},
{"experiment":30384,"c":11,"ratio":-0.073,"stdev":0.382,"median":-0.056,"zscore":-22.067},
{"experiment":30384,"c":12,"ratio":0.002,"stdev":0.379,"median":0.019,"zscore":2.533},
{"experiment":30384,"c":13,"ratio":-0.054,"stdev":0.39,"median":-0.0295,"zscore":-8.375},
{"experiment":30384,"c":14,"ratio":0.019,"stdev":0.376,"median":0.025,"zscore":6.447},
{"experiment":30384,"c":15,"ratio":-0.054,"stdev":0.421,"median":-0.0265,"zscore":-11},
{"experiment":30384,"c":16,"ratio":0.055,"stdev":0.375,"median":0.0695,"zscore":8.297},
{"experiment":30384,"c":17,"ratio":0.024,"stdev":0.394,"median":0.054,"zscore":3.767},
{"experiment":30384,"c":18,"ratio":-0.049,"stdev":0.36,"median":-0.018,"zscore":-11.902},
{"experiment":30384,"c":19,"ratio":0.095,"stdev":0.37,"median":0.1135,"zscore":10.24},
{"experiment":30384,"c":20,"ratio":0.157,"stdev":0.343,"median":0.174,"zscore":29.423},
{"experiment":30384,"c":21,"ratio":-0.091,"stdev":0.407,"median":-0.067,"zscore":-14},
{"experiment":30384,"c":22,"ratio":0.071,"stdev":0.381,"median":0.104,"zscore":7.329},
{"experiment":30384,"c":23,"ratio":0,"stdev":0,"median":0,"zscore":7.329},
{"experiment":30384,"c":24,"ratio":0,"stdev":0,"median":0,"zscore":7.329}]
The data contains an experiment id, chromosome number, ratio and some satistics. The array can contain data from various experiments, which all have a different id.
my js code currently looks like this:
<script>
function unique(list) {
var result = [];
$.each(list, function(i, e) {
if ($.inArray(e, result) == -1) result.push(e);
});
return result;
}
var margin = {top: 50, right: 50, bottom: 50, left: 50};
var width = 1000 - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
var threshold={upper:0.1,lower:-0.1};
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg = d3.select("#svg").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.json("{{settings.Base_url}}/templates/addons/data.json", function(error, data) {
if (error) throw error;
var expNames =unique(data.map(function(d) { return d.experiment; }));
x0.domain(data.map(function(d) { return d.c; }));
x1.domain(expNames).rangeRoundBands([0, x0.rangeBand()]);
y.domain([-1.5,1.5]);
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", -50)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Average Ratio/Chromosome");
var chr = svg.selectAll(".bar")
.data(data)
.enter().append("g")
.attr("class", "bar")
.attr("transform", function(d) { return "translate(" + x0(d.c) + ",0)"; });
chr.selectAll("rect")
.data(data)
.enter().append("rect")
.attr("x", function(d) {return x1(d.experiment);})
.attr("y", function(d) { return y(Math.max(0, d.ratio)); })
.attr("height", function(d) { return Math.abs(y(d.ratio)-y(0)); })
.attr("width", x1.rangeBand())
.style("fill", function(d) { return color(d.experiment); })
.style({"opacity":0.6,"stroke-width":"2"})
.text("test");
var legend = svg.selectAll(".legend")
.data(expNames.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
</script>
which results in a graph like this:
any ideas? I have a general idea where the error is, but cant seem to find a solution.
Note sure if I understand the question properly, but here's what I get:
You bind the data to the groups which you transform in x direction.
Afterwards you want to display two bars (for each experiment) in each group (c value)
If that's the case, you don't need to bind the data again for the bars, so it's just:
var chr = svg.selectAll(".bar")
.data(data)
.enter().append("g")
.attr("class", "bar")
.attr("transform", function (d) {
return "translate(" + x0(d.c) + ",0)";
});
chr.append("rect")
.attr("x", function (d) {
return x1(d.experiment);
})
...etc
See fiddle
Does that help?
The code below is working perfectly fine but I want to use another dataset. A dataset where the attributes are arrays themselves. They are structured likes this: [year, population, man, woman]. The year will be the X-axis and the other three will be displayed as bars next to each other. How can I make an triple bar chart? Where to start?
<script type="text/javascript">
//Width and height
var w = 500;
var h = 250;
var barPadding = 5;
//Dataset
var dataset = [10027, 10200, 10328, 10436, 10551, 10680, 10822, 10957, 11096, 11278,
11417, 11556, 11721, 11890 ];
//The other dataset
//[year, population, man, woman]
//var dataset = [[1950, 10027, 4998, 5029], [1950, 10027, 4998, 5029], [1950, 10027, 4998, 5029], etc];
//Scale
var x = d3.scale.ordinal().range([0, w])
var y = d3.scale.linear().range([h, 0]);
// Axis
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10);
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", function(d, i) {
return i * (w / dataset.length);
})
.attr("y", function(d) {
return h - (d / 50);
})
.attr("width", w / dataset.length - barPadding)
.attr("height", function(d) {
return d / 50;
})
.attr("fill", function(d) {
return "rgb(102, 0, 51)";
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis)
.style("text-anchor", "end")
.text("Years");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.5em")
.style("text-anchor", "end")
.text("Population in millions");
</script>
(little question: why doesn't my x-axis appear?)
Thanks in advance
Towards your little question: your x- and y-axis get rendered, but outside of the svg visible space. The common way for dealing with this is to add a margin inside the svg and render the chart with the width and height inside of the margin. This is described by the author of D3 as conventional margin
I have created a snippet with what you call a tripple bar chart.
This code is the grouped barchart of Bostock applied to your dataset.
I changed the dataset a little bit, so that each year is an object with the properties population, men, women and year. With this setup it is easer to process the values.
The idea behind the code for the grouped bar chart is to add a group element for each object in your dataset and render the bars inside this group.
Therefore you bind the dataset to the year groups.
Inside the years selection, each element is bound to the corresponding object from your dataset array.
If this all doesn't make that much sense to you, maybe you should read the Let's make a Bar Chart tutorials by Bostock. They give a great overview on the basic steps ;)
var dataset = [{year:1950, population:10000, men:4500, women:5500}, {year:1951, population:10200, men:5000, women:6200}, {year:1952, population:11000, men:6000, women:5000}, {year:1953, population:12000, men:5900, women:6100}];
// setup conventional margin, see http://bl.ocks.org/mbostock/3019563
var margin = {top: 20, right: 30, bottom: 30, left: 60},
width = 700 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// accessor functions for the 4 values
var year = function(d) { return d.year; };
var population = function(d) { return d.population; };
var men = function(d) { return d.men; };
var women = function(d) { return d.women; };
var valueObject = function(d) { return [{name:"population", value:population(d)},{name:"men", value: men(d)}, {name: "women", value: women(d)}]; };
var color = d3.scale.ordinal()
.domain(["population","men","women"])
.range(["#31a354","#3182bd","#e6550d"]);
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .2)
.domain(dataset.map(year)); // use the year for the xAxis
var x1 = d3.scale.ordinal()
.domain(["population","men","women"])
.rangeRoundBands([0, x0.rangeBand()]);
var y = d3.scale.linear()
.range([height, 0])
.domain([0, d3.max(dataset.map(population))]); // use the population for calculating the maximum value
var xAxis = d3.svg.axis()
.scale(x0)
.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);
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("Population");
var years = svg.selectAll(".year")
.data(dataset)
.enter()
.append("g")
.attr("class", "year")
.attr("transform", function(d) { return "translate(" + x0(year(d)) + ",0)"; });
years.selectAll("rect")
.data(valueObject)
.enter()
.append("rect")
.attr("width", x1.rangeBand())
.attr("x", function(d) { return x1(d.name); })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.attr("fill", function(d) { return color(d.name); });
var legend = svg.selectAll(".legend")
.data(["population","men","women"])
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
I've been searching around for a while now for a possible solution to this problem. I've created a bar chart for a company dashboard based on this graph.
http://bl.ocks.org/mbostock/3887051
This is working great, however what I would like to do now is display some of the external data that I have in text underneath the graph so for example. "Total Sales Today = ......" instead of just a monthly graph.
So I guess I'm asking is there a way to do this in d3.js using a text element or anything similar? if not pointing me to something that can would be great. Ill also add that the data is coming from a csv.
This is the code:
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
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 + ")");
d3.csv("data.csv", function(error, data) {
var Names = d3.keys(data[0]).filter(function(key) { return key !== "Month"; });
data.forEach(function(d) {
d.Total = Names.map(function(name) { return {name: name, value: +d[name]}; });
});
x0.domain(data.map(function(d) { return d.Month; }));
x1.domain(Names).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function(d) { return d3.max(d.Total, function(d) { return d.value; }); })]);
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("Sales Value £");
var text = svg.selectAll("text")
.data(data)
.enter()
.append("text");
var Month = svg.selectAll(".Month")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x0(d.Month) + ",0)"; });
Month.selectAll("rect")
.data(function(d) { return d.Total; })
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("x", function(d) { return x1(d.name); })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.style("fill", function(d) { return color(d.name); });
var legend = svg.selectAll(".legend")
.data(Names.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
If you need any more info just say
Cheers!
In your HTML file, create a div for your chart and a div below that for your label
<div id="chart"></div>
<div id="label"></div>
In your d3 code, instead of appending an svg element to the body, select the "chart" div and append an svg element to it.
var svg = d3.select("#chart").append("svg"). ...
Use that svg element to draw your chart like in your above code.
At some point in your code calculate the total sales for the day and create a variable called totalSales. You could do this by summing up the sales value when you draw the chart, but it doesn't really matter as long as totalSales is calculated.
Create another svg element on the "label" div
var svgLabel = d3.select("#label").append("svg") ...
Use this svgLabel to write a text element with totalSales as the text attribute.
svg.append("text")
...
.text(totalSales);
Good afternoon.
I need to automatic update the size of the chart.
My code is above.
My data is something like this, when the data is small i do not have problem but when it is big the values in xAxis and the bars are overlapping.
var data = [
{key:1, value:5},
{key:2, value:10},
{key:3, value:15},
{key:4, value:26},
{key:5, value:33}
];
var margin = {
top: 30,
right: 10,
bottom: 30,
left: 30
},
width = 900 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.domain(data.map(function(d) {
return d.key;
}))
.rangeRoundBands([margin.left, width], 0.05);
var y = d3.scale.linear()
.domain([0, d3.max(data, function(d) {
return d.value;
})])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var key = function(d) {
return d.key;
};
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right + 10)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.text("Your tooltip info")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("text")
.attr("x", (width / 2))
.attr("y", 0 - (margin.top / 2))
.attr("text-anchor", "middle")
.style("font-size", "16px")
.style("text-decoration", "underline")
.text("Log(number sts) vs Nodes - Gen" + " " + startGen + " "+"to" + " "+ endGen)
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(-30," + height + ")")
.call(xAxis)
.append("text")
.attr("x", width)
.attr("dy", 30)
.attr("text-anchor", "end")
.text("Number of nodes");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -30)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Log(Number Sts)");
var bars = svg.selectAll("rect")
.data(data, key)
.enter().append("rect")
.attr("x", function(d) {
return x(d.key) + x.rangeBand() / 2 - 40;
})
.attr("y", function(d) {
return y(d.value);
})
.attr("width", 20)
.attr("height", function(d) {
return height - y(d.value);
})
.style("fill", "blue");
If you want to size the chart according to how much data you have then you can simply replace your "width" variable with a calculation: something like:
width = Math.min(900, 20 * data.length);
But perhaps what you mean is to size the bars based on how much room there is? You are already using x.rangeBand that gives you the available range width - try using that for the bar width
...
.attr("width", x.rangeBand())
If you want to get fancy you can have finer control over the bar width and gap. Something like:
var barWidth = Math.max(1, 0.9 * x.rangeBand());
var halfGap = Math.max(0, x.rangeBand() - barWidth) / 2;
var bars = svg.selectAll("rect")
.data(data, key)
.enter().append("rect")
.attr("x", function(d) {
return x(d.key) + halfGap - 30 ;
})
.attr("width", barWidth)
...
You can try the fiddle here