appearance of bar charts when you refine data

117 views
Skip to first unread message

Spencer James

unread,
Jul 5, 2013, 2:16:25 AM7/5/13
to google-visua...@googlegroups.com
I'm using Google Spreadsheets in conjunction with the Google Visualization API. I like the way this bar chart appears (it keeps going way down the page):

... but when I refine one of the values at the top, for example to just a certain age-sex group, the size of the bars increases greatly so it sort of seems like the chart is trying to retain its original dimensions. I would really like the size of the bars to just stay the same as in the first image, though. This is what they look like:


It gets really ugly if I stratify it down even further because the bars get so big:


I would love any ideas on how to make this look nicer so that they retain the original bar chart size. 

Here is the code I use for the bar charts:

<!--

You are free to copy and use this sample in accordance with the terms of the

Apache license (http://www.apache.org/licenses/LICENSE-2.0.html)

-->


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

  <head>

    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>

    <title>

      RICE2: Mobile Disease Surveillance in Vietnam

    </title>

<style>

a:link {color:#000000;}    /* unvisited link */

a:visited {color:#000000;} /* visited link */

a:hover {color:#000000;}   /* mouse over link */

a:active {color:#000000;}  /* selected link */

</style>


    <script type="text/javascript" src="http://www.google.com/jsapi"></script>

    <script type="text/javascript">

      google.load('visualization', '1.1', {packages: ['controls', 'corechart']});

    </script>

    <script type="text/javascript">

      function drawVisualization() {

       var query = new google.visualization.Query(

'//docs.google.com/spreadsheet/tq?key=XXXXXXXXX&transpose=0&headers=1&range=A1%3AJ2571&gid=0&pub=1');

query.setQuery('select B,H,G,D,sum(I),sum(J) group by D,B,H,G');


   query.send(handleQueryResponse);


}

function handleQueryResponse(response) {

      

        if (response.isError()) {

        alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());

        return;

      }

    

      var data = response.getDataTable();

     

        // Define a slider control for the Age column.

        var slider = new google.visualization.ControlWrapper({

          'controlType': 'NumberRangeFilter',

          'containerId': 'control1',

          'options': {

            'filterColumnIndex': 1,

          'ui': {'labelStacking': 'vertical'}

          }

        });

      

        // Define a category picker control for the Gender column

        var categoryPicker = new google.visualization.ControlWrapper({

          'controlType': 'CategoryFilter',

          'containerId': 'control2',

          'options': {

            'filterColumnIndex': 2,

            'ui': {

            'labelStacking': 'vertical',

              'allowTyping': true,

              'allowMultiple': true

            }

          }

        });

      

      // Define a category picker control for the commune column

        var categoryPickerCommune = new google.visualization.ControlWrapper({

          'controlType': 'CategoryFilter',

          'containerId': 'control3',

          'options': {

            'filterColumnIndex': 0,

            'ui': {

            'labelStacking': 'vertical',

              'allowTyping': true,

              'allowMultiple': true

            }

          }

        });

        

        // Define a category picker control for the commune column

        var categoryPickerDistrict = new google.visualization.ControlWrapper({

          'controlType': 'CategoryFilter',

          'containerId': 'control4',

          'options': {

            'filterColumnIndex': 3,

            'ui': {

            'labelStacking': 'vertical',

              'allowTyping': true,

              'allowMultiple': true

            }

          }

        });

        

        // Define a column chart

      

        var columnChart = new google.visualization.ChartWrapper({

    chartType: 'BarChart',

    options: {

    'title': 'Incident Cases of Diarrhea and Influenza by Commune, Age (10 year groups), and Sex (0=F,1=M)',            

    'width':'1600',

            'height':'12000',

            'chartArea': {'left': 115, 'top': 15, 'right': 0, 'bottom': 0},

'hAxis': {title: "Cases"},

'vAxis': {title: "Commune"},

//'hAxis.viewWindowMode': 'pretty',

'isStacked': true,

'fontSize': 10,

//'hAxis.showTextEvery': 4,

//hAxis: {showTextEvery: 20},

            },

    containerId: 'chart1',

    view: { 'columns': [{

        type: 'string',

        label: 'Commune, Age, Sex', // set the label to whatever you want

        calc: function (dt, row) {

            return dt.getFormattedValue(row, 0) + ', ' + dt.getFormattedValue(row, 1) + ', ' + dt.getFormattedValue(row, 2);

        }

    }, 4, 5]

    

    }

    

    


  });

      

      

        // Create a dashboard

        new google.visualization.Dashboard(document.getElementById('dashboard')).

            // Establish bindings, declaring the both the slider and the category

            // picker will drive both charts.

            bind([slider, categoryPicker, categoryPickerCommune, categoryPickerDistrict], [columnChart]).

            // Draw the entire dashboard.

            draw(data);

      }

      


      google.setOnLoadCallback(drawVisualization);

    </script>

  </head>

  <body style="font-family: Arial;border: 0 none;">

<table cellpadding="0" cellspacing="0">

<tr>

<td style='width: 50%'>

<div style="font-size: small; font-family:  Menlo, Lucida Sans Unicode">

RICE2: live SMS-based disease surveillance & outbreak detection in northern Vietnam

</div>

</td>

<td style='width: 50%'>

<div style="font-size: small; font-family:  Menlo, Lucida Sans Unicode"><p align="right"><a href=chart.html>chart</a> | <a href=table.html>table</a> | <a href=time.html>time</a> | <a href=heatmap.html>heatmap</a> | <a href=rawdata.html>raw data</a> | <a href=index.html>home</a></p>

</div>

</td>

</table>

    <div id="dashboard">

<table>

  <tr>

  <td style='width: 75px'> </td><td><div id="control4"></div><td><div id="control3"></div> <td><div id="control2"></div><td><div id="control1"></div>

</tr>

  </table>

<table>

        <tr>

          <td style='width: 100%'>

            <div style="float: left;" id="chart1"></div>

          </td>

        </tr>

</table>

  </body>

</html>


asgallant

unread,
Jul 5, 2013, 10:28:08 AM7/5/13
to google-visua...@googlegroups.com
The problem is that you keep the height the same, so two things are happening here: 1) the data points are being evenly dispersed through the vAxis, so when you cut the number of points in half, you double the spacing between points, and 2) with more space between points, the bars draw wider.  You can set the width of your bars at a fixed value by setting the bar.groupWidth option to an integer value of the width of the bars in pixels.  The spacing you can fix by changing the height of the chart based on the number of rows of data you have.

Spencer James

unread,
Jul 5, 2013, 10:49:06 PM7/5/13
to google-visua...@googlegroups.com
Thanks for the reply. I can't seem to get groupWidth to have any effect, though. I removed the height specification for the chart and then varied the groupWidth option by orders of magnitude (and also tried every variant on syntax I could think of):

var columnChart = new google.visualization.ChartWrapper({
    chartType: 'BarChart',
    options: {
    'title': 'Incident Cases of Diarrhea and Influenza by Commune, Age (10 year groups), and Sex (0=F,1=M)',            
    'width':'1600',
            //'height':'12000',
            'chartArea': {'left': 115, 'top': 15, 'right': 0, 'bottom': 0},
'hAxis': {title: "Cases"},
'vAxis': {title: "Commune"},
//'hAxis.viewWindowMode': 'pretty',
'isStacked': true,
'bar.groupWidth': '500',
'fontSize': 10,
//'hAxis.showTextEvery': 4,
//hAxis: {showTextEvery: 20},
            },
    containerId: 'chart1',
    view: { 'columns': [{
        type: 'string',
        label: 'Commune, Age, Sex', // set the label to whatever you want
        calc: function (dt, row) {
            return dt.getFormattedValue(row, 0) + ', ' + dt.getFormattedValue(row, 1) + ', ' + dt.getFormattedValue(row, 2);
        }
    }, 4, 5]
    
    }
    
    

  });
      

but it continues to look like this. It seems like the groupWidth isn't having any effect.

Inline image 1


--
You received this message because you are subscribed to a topic in the Google Groups "Google Visualization API" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-visualization-api/tM385bKbDCs/unsubscribe.
To unsubscribe from this group and all its topics, send an email to google-visualizati...@googlegroups.com.
To post to this group, send email to google-visua...@googlegroups.com.
Visit this group at http://groups.google.com/group/google-visualization-api.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

image.png

asgallant

unread,
Jul 6, 2013, 11:43:31 AM7/6/13
to google-visua...@googlegroups.com
It's properly:

bar: {
    groupWidth: 20
To unsubscribe from this group and all its topics, send an email to google-visualization-api+unsub...@googlegroups.com.

Spencer James

unread,
Jul 6, 2013, 11:58:51 AM7/6/13
to google-visua...@googlegroups.com
Hmm, thanks for the advice again but it still is producing the same result. This code:

        var columnChart = new google.visualization.ChartWrapper({
    chartType: 'BarChart',
    options: {
    'title': 'Incident Cases of Diarrhea and Influenza by Commune, Age (10 year groups), and Sex (0=F,1=M)',            
    'width':'1600',
            //'height':'12000',
            'chartArea': {'left': 115, 'top': 15, 'right': 0, 'bottom': 0},
'hAxis': {title: "Cases"},
'vAxis': {title: "Commune"},
//'hAxis.viewWindowMode': 'pretty',
'isStacked': true,
'bar': {
    groupWidth: 20
    },
'fontSize': 10,
//'hAxis.showTextEvery': 4,
//hAxis: {showTextEvery: 20},
            },
    containerId: 'chart1',
    view: { 'columns': [{
        type: 'string',
        label: 'Commune, Age, Sex', // set the label to whatever you want
        calc: function (dt, row) {
            return dt.getFormattedValue(row, 0) + ', ' + dt.getFormattedValue(row, 1) + ', ' + dt.getFormattedValue(row, 2);
        }
    }, 4, 5]
    
    }
    
    

  });
produces this graph (and it doesn't change if I vary groupWidth by orders of magnitude, eg 20, 200, 2000:

Inline image 1


To unsubscribe from this group and all its topics, send an email to google-visualizati...@googlegroups.com.
image.png

asgallant

unread,
Jul 6, 2013, 12:03:03 PM7/6/13
to google-visua...@googlegroups.com
The API calculates a maximum for the groupWidth at chart area height / number of rows of data.  Setting the bar.groupWidth option to a value higher than this will have no effect.  Try filtering the data and see if that has any effect.
To unsubscribe from this group and all its topics, send an email to google-visualization-api+unsubscr...@googlegroups.com.
To post to this group, send email to google-visua...@googlegroups.com.

Spencer James

unread,
Jul 6, 2013, 9:04:41 PM7/6/13
to google-visua...@googlegroups.com
Oh, okay, I see! That actually looks good now when I filter it. So regarding the whitespace between bars, I suppose what I want is for the height of the chart to always be groupWidth * # of rows of data in the filtered query. Is it possible to adjust the chart height like that? The bar width is now the correct size when I filter, but I still end up with huge amounts of white space between bars as I filter more and more. Or are there any other ways to adjust appropriately to get the appearance I want? Thank you for the help -- my programming ability is somewhat limited so I really appreciate it. 

Spence


To unsubscribe from this group and all its topics, send an email to google-visualizati...@googlegroups.com.

asgallant

unread,
Jul 6, 2013, 9:47:52 PM7/6/13
to google-visua...@googlegroups.com
You want to trigger a height change whenever the filters change values, something like this:

function updateChartHeight() {
    var rows = columnChart.getDataTable().getNumberOfRows();
    // padding is the width you want for the chart's legend
    // you may need to fiddle with this a bit to get it right
    var height = rows * groupWidth + padding;
    chart.setOption('height', height);
    chart.draw();
}
// update the chart height when the filters change values
google.visualization.events.addListener(slider, 'statechange', updateChartHeight);
google.visualization.events.addListener(categoryPicker, 'statechange', updateChartHeight);
google.visualization.events.addListener(categoryPickerCommune, 'statechange', updateChartHeight);
google.visualization.events.addListener(categoryPickerDistrict, 'statechange', updateChartHeight);


You may want to experiment with using the chartArea.height and chartArea.top options as well (height controls the height of the chartArea, top controls where it starts from the top of the chart).
Reply all
Reply to author
Forward
0 new messages