Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maximum width for column in bar chart

Tags:

d3.js

I'm looking for a way of limiting the column width in a chart, I'm sure this ought to be relatively easy but I cant find a way of doing it.

I'm populating a chart from some dynamic data, where the number of columns can vary quite dramatically - between 1 and 20.

e.g: sample of csv

Location,Col1
"Your house",20

Location,Col1,Col2,Col3,Col4,Col5
"My House",12,5,23,1,5

This is working fine, and the col widths are dynamic, however when there is only one column in the data, I end up with one bar of width 756 (the whole chart), and I dont like the way this looks.

What I'd like to do is only ever have a maximum column of width 100px irrespective of the number of columns of data.

Below is my script for the chart

Many thanks,

<script>
var margin = {
    top : 40,
    right : 80,
    bottom : 80,
    left : 40
}, 
width = 960 - margin.left - margin.right, 
height = 500 - margin.top - margin.bottom;

var x = d3.scale.linear().range([ 0, width ]);

var y = d3.scale.linear().range([ height, 0 ]);

var x0 = d3.scale.ordinal()
    .rangeRoundBands([0, width], .05);

var x1 = d3.scale.ordinal();

var y = d3.scale.linear()
    .range([height, 0]);

var chart = d3.select("body").append("svg")
    .attr("class","chart")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var legendChart = d3.select("body").append("svg")
    .attr("class","chart")
    .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("/sampledata.csv.txt", function(error, data) {
    // Use the first row of csv for header names 
    var reasonNames = d3.keys(data[0]).filter(function(key) {
        return key !== "Location";
    });
    //console.log(reasonNames);

    data.forEach(function(d) {
        d.reasons = reasonNames.map(function(name) {
            return {
                name : name,
                value : +d[name]
            };
        });
        //console.log(d.reasons);
    });

    x0.domain(data.map(function(d) {return d.Location; }));
    x1.domain(reasonNames).rangeRoundBands([0, x0.rangeBand()]);

    console.log(x0.rangeBand());

    y.domain([0, d3.max(data, function(d) { return d3.max(d.reasons, function(d) { return d.value; }); })]);

    var maxVal = d3.max(data, function(d) { return d3.max(d.reasons, function(d) { return d.value; }); });
    //console.log(maxVal);

    var xAxis = d3.svg.axis()
        .scale(x0)
        .orient("bottom");

    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left")
        //.tickFormat(d3.format(".2s"));

    chart.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);

    chart.append("g")
        .attr("class", "y axis")
        .call(yAxis);

    var location = chart.selectAll(".name")
        .data(data)
      .enter().append("g")
        .attr("class", "g")
        .attr("transform", function(d) { return "translate(" + x0(d.Location) + ",0)"; });

    location.selectAll("rect")
        .data(function(d) { return d.reasons; })
      .enter().append("rect")
        .attr("width", x1.rangeBand()-2)
        .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,i) { return "#"+3+"9"+i; /*color(d.name);*/ });

    chart.selectAll("text")
        .data(data)
      .enter().append("text")
        .attr("x", function(d) { return x1(d.name)+ x.rangeBand() / 2; })
        .attr("y", function(d) { return y(d.value); })
        .attr("dx", -3) // padding-right
        .attr("dy", ".35em") // vertical-align: middle
        .attr("text-anchor", "end") // text-align: right
        .text("String");

    var legend = legendChart.selectAll(".legend")
        .data(reasonNames.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("x", 18)
        .attr("width", 18)
        .attr("height", 18)
        .style("fill", function(d, i) {/*console.log(i);*/return "#" + 3 + "9" + i;
    });

    legend.append("text")
        //.attr("x", width - 24)
        .attr("x", 48)
        .attr("y", 9).attr("dy",".35em")
        //.style("text-anchor", "end")
        //.text(function(d,i) { return String.fromCharCode((65+i))+i; });
        .text(function(d) { return d; });
    });


</script>
like image 281
user1884914 Avatar asked Dec 07 '12 09:12

user1884914


People also ask

What are width of bar graphs?

The width of a bar, in and of itself, is not the issue. It is the ratio of length to width that we should consider. This is because our perception of a bar's length is influenced by its width. Two graphs with bars of the same length do not seem the same if the bars in one are much wider than the bars in the other.

How do you widen columns in a bar chart?

The solution for this is to click the Excel chart's X axis, right click and choose Format Axis. Select Axis Options and then click on Text Axis to select it. This changes the way the axis is plotted giving wider bars. You can then adjust the gap width if necessary to make them wider.

What is the default width of bars in a bar chart?

The default value for width parameter is 0.8. We may assign a new value in the range [0.0, 1.0]. The width(s) of the bars which takes float or array-like. The default value is: 0.8.

Can the bars of a bar graph be different widths?

A bar graph is a pictorial representation of the numerical data by a number of bars of uniform width erected horizontally or vertically with equal spacing between them. The height of the bars may vary but width remains the same.


2 Answers

The easiest way to achieve this is by changing the line

.attr("width", x1.rangeBand()-2)

to

.attr("width", Math.min(x1.rangeBand()-2, 100))

You might also want to adjust the starting position and/or padding.

like image 120
Lars Kotthoff Avatar answered Oct 25 '22 05:10

Lars Kotthoff


Code for adjusting starting position if anyone is stuck on it:

.attr("x", function(d, i) { return x1(d.seriesName) + (x1.rangeBand() - 100)/2 ;})

P.S. : referring answer from Lars.

like image 24
Rajesh Kolhapure Avatar answered Oct 25 '22 05:10

Rajesh Kolhapure