【问题标题】:Google Bar Chart with Percentage of Total and with Category Filters带有总百分比和类别过滤器的 Google 条形图
【发布时间】:2017-09-11 09:54:59
【问题描述】:

我对谷歌图表相当陌生,并试图创建一个占总数百分比的条形图,以及使用谷歌仪表板控件过滤数据的能力......我遵循了这个(感谢@asgallant! ) google.visualization.ChartWrapper Group Columns View 并且能够获得一个条形图,该条形图从谷歌表格中获取数据,并绘制带有计数的图表,并且还能够使用谷歌类别过滤器过滤数据。

但是,这是我卡住的地方 - 当我尝试添加另一列(数据视图)来计算总数时(以便我可以使用百分比绘制图表并在条形标签中显示百分比) - 我的图表仍在使用计数进行绘图.. 任何人都可以让我知道我在这里出了什么问题:

function drawVisualization() {

    var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1LBoS8Q7qdpWVjks3FytQAefThzY3VbAHllf04nE6qO8/edit?gid=1629614877&range=A:D');
    query.send(handleQueryResponse);

    function handleQueryResponse(response) {
     if (response.isError()) {return; }
    var data = response.getDataTable();


        // Define category pickers for All Filters
        var CardTier = new google.visualization.ControlWrapper({
            'controlType': 'CategoryFilter',
            'containerId': 'control1',
            'options': {
                'filterColumnLabel': 'CardTier Filter',
                'ui': {
                    'labelStacking': 'vertical',
                    'allowTyping': false,
                    'allowMultiple': false
                }
            }
        });

        var Campaign = new google.visualization.ControlWrapper({
            'controlType': 'CategoryFilter',
            'containerId': 'control2',
            'options': {
                'filterColumnLabel': 'Campaign Filter',
                'ui': {
                    'labelStacking': 'vertical',
                    'allowTyping': false,
                    'allowMultiple': false
                }
            }
        });


        // Define a bar chart to show 'Population' data
        var barChart = new google.visualization.ChartWrapper({
            'chartType': 'BarChart',
            'containerId': 'chart1',
            'options': {
                'width': 400,
                'height': 300,
                'chartArea': {top: 0, right: 0, bottom: 0}
            },
            // Configure the barchart to use columns 0 (Card Tier) and 1 (Campaign Filter) (Basically the filters)
            'view': {'columns': [0, 1]}
        });

        var proxyTable = new google.visualization.ChartWrapper({
            chartType: 'Table',
            containerId: 'proxyTable',
            options: {
                // minimize the footprint of the table in HTML
                page: 'enable',
                pageSize: 1
            },
            view: {
                columns: [0]
            }
        });



        // create a "ready" event handler for proxyTable the handles data aggregation and drawing barChart
        // Add The question's column index here. We want to draw Status so we Group 2 with dt and also its count...
        google.visualization.events.addListener(proxyTable, 'ready', function () {
            var dt = proxyTable.getDataTable();
            var groupedData = google.visualization.data.group(dt, [2], [{
                column: 3,
                type: 'number',
                label: dt.getColumnLabel(2),
                aggregation: google.visualization.data.count
            }]);

      var view = new google.visualization.DataView(groupedData);
      view.setColumns([0, 1, {
        calc: function (dt, row) {
          var amount =  formatShort.formatValue(dt.getValue(row, 1));
          var percent = formatPercent.formatValue(dt.getValue(row, 1) / groupedData.getValue(0, 1));
          return amount + ' (' + percent + ')';
        },
        type: 'string',
        role: 'annotation'
      }]);


            // after grouping, the data will be sorted by column 0, then 1, then 2
            // if you want a different order, you have to re-sort
            barChart.setDataTable(view);
            barChart.draw();

    });



        // Create the dashboard.
        new google.visualization.Dashboard(document.getElementById('dashboard')).
        // Configure the controls :
        bind(CardTier, Campaign).
        bind(Campaign, proxyTable).
        // Draw the dashboard
        draw(data);
    }
    }

    google.load('visualization', '1', {packages:['corechart', 'controls', 'table'], callback: drawVisualization});




    </script>
    </head>


      <body>

    <div id="dashboard">
        <table>
            <tr style='vertical-align: top'>
                <td style='width: 300px; font-size: 0.9em;'>
                    <div id="control1"></div>
                    <div id="control2"></div>
                </td>
                <td style='width: 600px'>
                    <div style="float: left;" id="chart1"></div>
                    <div style="float: left;" id="chart2"></div>
                </td>
            </tr>
        </table>
        <div id="proxyTable" style="display: none;"></div>
    </div>

    </body>  
    </html>

【问题讨论】:

    标签: javascript charts google-visualization bar-chart


    【解决方案1】:

    对于初学者,推荐使用较新的库loader.js

    <script src="https://www.gstatic.com/charts/loader.js"></script>
    

    而不是jsapi,根据release notes...

    通过jsapi 加载程序仍然可用的 Google 图表版本不再持续更新。请从现在开始使用新的 gstatic 加载器。

    这只会更改load 语句,请参阅下面的工作 sn-p...


    接下来,没有看到数字格式化程序的定义
    formatShortformatPercent
    需要添加那些


    groupedData 将为您提供每种状态的总数
    获取所有行的总数,
    需要使用modifier函数
    这会将所有行的第一列的值更改为 'Total'
    允许group 方法聚合所有行

      var totalData = google.visualization.data.group(
        dataTable,
        [{column: 0, type: 'string', modifier: function () {return 'Total';}}],
        [{
          column: 3,
          type: 'number',
          label: dataTable.getColumnLabel(2),
          aggregation: google.visualization.data.count
        }]
      );
    

    最后,从barChart 中删除view 选项
    因为我们提供了我们想要绘制的view


    请参阅以下工作 sn-p...

    google.charts.load('current', {
      callback: drawVisualization,
      packages: ['corechart', 'controls', 'table']
    });
    
    function drawVisualization() {
      var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1LBoS8Q7qdpWVjks3FytQAefThzY3VbAHllf04nE6qO8/edit?gid=1629614877&range=A:D');
      query.send(handleQueryResponse);
    
      function handleQueryResponse(response) {
        if (response.isError()) {return; }
        var data = response.getDataTable();
    
        // Define category pickers for All Filters
        var CardTier = new google.visualization.ControlWrapper({
          'controlType': 'CategoryFilter',
          'containerId': 'control1',
          'options': {
            'filterColumnLabel': 'CardTier Filter',
            'ui': {
              'labelStacking': 'vertical',
              'allowTyping': false,
              'allowMultiple': false
            }
          }
        });
    
        var Campaign = new google.visualization.ControlWrapper({
          'controlType': 'CategoryFilter',
          'containerId': 'control2',
          'options': {
            'filterColumnLabel': 'Campaign Filter',
            'ui': {
              'labelStacking': 'vertical',
              'allowTyping': false,
              'allowMultiple': false
            }
          }
        });
    
        // Define a bar chart to show 'Population' data
        var barChart = new google.visualization.ChartWrapper({
          'chartType': 'BarChart',
          'containerId': 'chart1',
          'options': {
            'width': 400,
            'height': 300,
            'chartArea': {top: 0, right: 0, bottom: 0}
          }
        });
    
        var proxyTable = new google.visualization.ChartWrapper({
          chartType: 'Table',
          containerId: 'proxyTable',
          options: {
            // minimize the footprint of the table in HTML
            page: 'enable',
            pageSize: 1
          },
          view: {
            columns: [0]
          }
        });
    
        // create a "ready" event handler for proxyTable the handles data aggregation and drawing barChart
        // Add The question's column index here. We want to draw Status so we Group 2 with dt and also its count...
        google.visualization.events.addListener(proxyTable, 'ready', function () {
          var formatShort = new google.visualization.NumberFormat({
            pattern: 'short'
          });
          var formatPercent = new google.visualization.NumberFormat({
            pattern: '0.0%'
          });
          var dataTable = proxyTable.getDataTable();
    
          // group by status
          var groupedData = google.visualization.data.group(
            dataTable,
            [2],
            [{
              column: 3,
              type: 'number',
              label: dataTable.getColumnLabel(2),
              aggregation: google.visualization.data.count
            }]
          );
    
          // status total
          var totalData = google.visualization.data.group(
            dataTable,
            [{column: 0, type: 'string', modifier: function () {return 'Total';}}],
            [{
              column: 3,
              type: 'number',
              label: dataTable.getColumnLabel(2),
              aggregation: google.visualization.data.count
            }]
          );
    
          var view = new google.visualization.DataView(groupedData);
          view.setColumns([0, 1, {
            calc: function (dt, row) {
              var amount =  dt.getValue(row, 1);
              var total = totalData.getValue(0, 1);
              var percent = 0;
              if (total > 0) {
                percent = amount / total;
              }
              return formatShort.formatValue(amount) + ' (' + formatPercent.formatValue(percent) + ')';
            },
            type: 'string',
            role: 'annotation'
          }]);
    
          // after grouping, the data will be sorted by column 0, then 1, then 2
          // if you want a different order, you have to re-sort
          barChart.setDataTable(view);
          barChart.draw();
        });
    
        // Create the dashboard.
        new google.visualization.Dashboard(document.getElementById('dashboard')).
        // Configure the controls :
        bind(CardTier, Campaign).
        bind(Campaign, proxyTable).
        // Draw the dashboard
        draw(data);
      }
    }
    <script src="https://www.gstatic.com/charts/loader.js"></script>
    <div id="control1"></div>
    <div id="control2"></div>
    <div id="chart1"></div>
    <div id="proxyTable"></div>

    更新

    绘制百分比而不是计数,
    只需要将另一个计算列添加到view

    至于显示零值,
    使用原始数据表获取不同的状态值列表
    检查状态是否存在于groupedData
    如果没有,请为状态添加一行

      // add back missing status
      var statusValues = data.getDistinctValues(2);
      statusValues.forEach(function (status) {
        var statusRow = groupedData.getFilteredRows([{
          column: 0,
          value: status
        }]);
        if (statusRow.length === 0) {
          groupedData.addRow([
            status,
            0
          ]);
        }
      });
      groupedData.sort([{column: 0}]);
    

    请参阅以下工作 sn-p...

    google.charts.load('current', {
      callback: drawVisualization,
      packages: ['corechart', 'controls', 'table']
    });
    
    function drawVisualization() {
      var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1LBoS8Q7qdpWVjks3FytQAefThzY3VbAHllf04nE6qO8/edit?gid=1629614877&range=A:D');
      query.send(handleQueryResponse);
    
      function handleQueryResponse(response) {
        if (response.isError()) {return; }
        var data = response.getDataTable();
    
        // Define category pickers for All Filters
        var CardTier = new google.visualization.ControlWrapper({
          'controlType': 'CategoryFilter',
          'containerId': 'control1',
          'options': {
            'filterColumnLabel': 'CardTier Filter',
            'ui': {
              'labelStacking': 'vertical',
              'allowTyping': false,
              'allowMultiple': false
            }
          }
        });
    
        var Campaign = new google.visualization.ControlWrapper({
          'controlType': 'CategoryFilter',
          'containerId': 'control2',
          'options': {
            'filterColumnLabel': 'Campaign Filter',
            'ui': {
              'labelStacking': 'vertical',
              'allowTyping': false,
              'allowMultiple': false
            }
          }
        });
    
        // Define a bar chart to show 'Population' data
        var barChart = new google.visualization.ChartWrapper({
          'chartType': 'BarChart',
          'containerId': 'chart1',
          'options': {
            'width': 400,
            'height': 300,
            'chartArea': {top: 0, right: 0, bottom: 0}
          }
        });
    
        var proxyTable = new google.visualization.ChartWrapper({
          chartType: 'Table',
          containerId: 'proxyTable',
          options: {
            // minimize the footprint of the table in HTML
            page: 'enable',
            pageSize: 1
          },
          view: {
            columns: [0]
          }
        });
    
        // create a "ready" event handler for proxyTable the handles data aggregation and drawing barChart
        // Add The question's column index here. We want to draw Status so we Group 2 with dt and also its count...
        google.visualization.events.addListener(proxyTable, 'ready', function () {
          var formatShort = new google.visualization.NumberFormat({
            pattern: 'short'
          });
          var formatPercent = new google.visualization.NumberFormat({
            pattern: '0.0%'
          });
          var dataTable = proxyTable.getDataTable();
    
          // group by status
          var groupedData = google.visualization.data.group(
            dataTable,
            [2],
            [{
              column: 3,
              type: 'number',
              label: dataTable.getColumnLabel(2),
              aggregation: google.visualization.data.count
            }]
          );
    
          // add back missing status
          var statusValues = data.getDistinctValues(2);
          statusValues.forEach(function (status) {
            var statusRow = groupedData.getFilteredRows([{
              column: 0,
              value: status
            }]);
            if (statusRow.length === 0) {
              groupedData.addRow([
                status,
                0
              ]);
            }
          });
          groupedData.sort([{column: 0}]);
    
          // status total
          var totalData = google.visualization.data.group(
            dataTable,
            [{column: 0, type: 'string', modifier: function () {return 'Total';}}],
            [{
              column: 3,
              type: 'number',
              label: dataTable.getColumnLabel(2),
              aggregation: google.visualization.data.count
            }]
          );
    
          var view = new google.visualization.DataView(groupedData);
          view.setColumns([0, {
            calc: function (dt, row) {
              var amount =  dt.getValue(row, 1);
              var total = totalData.getValue(0, 1);
              var percent = 0;
              if (total > 0) {
                percent = amount / total;
              }
              return {
                v: percent,
                f: formatPercent.formatValue(percent)
              };
            },
            type: 'number',
            label: 'Percent'
          }, {
            calc: function (dt, row) {
              var amount =  dt.getValue(row, 1);
              var total = totalData.getValue(0, 1);
              var percent = 0;
              if (total > 0) {
                percent = amount / total;
              }
              return formatPercent.formatValue(percent) + ' (' + formatShort.formatValue(amount) + ')';
            },
            type: 'string',
            role: 'annotation'
          }]);
    
          // after grouping, the data will be sorted by column 0, then 1, then 2
          // if you want a different order, you have to re-sort
          barChart.setDataTable(view);
          barChart.draw();
        });
    
        // Create the dashboard.
        new google.visualization.Dashboard(document.getElementById('dashboard')).
        // Configure the controls :
        bind(CardTier, Campaign).
        bind(Campaign, proxyTable).
        // Draw the dashboard
        draw(data);
      }
    }
    <script src="https://www.gstatic.com/charts/loader.js"></script>
    <div id="control1"></div>
    <div id="control2"></div>
    <div id="chart1"></div>
    <div id="proxyTable"></div>

    更新 2

    求一道选择题的总分,
    使用计算列创建视图
    新列应测试所有问题列不为空
    然后汇总计算列上的视图

    请参阅以下工作 sn-p...

    google.charts.load('current', {
      callback: drawVisualization,
      packages: ['corechart', 'controls', 'table']
    });
    
    function drawVisualization() {
      var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/19VWNZkHG5GEuYCibDmtOlKblKiOWcx94Wi9jyuhvEUo/edit#gid=0');
      query.setQuery('select A,B,C,D,E,F,G');
      query.send(handleQueryResponse);
    
      function handleQueryResponse(response) {
        if (response.isError()) {return;}
        var data = response.getDataTable();
    
        var view = new google.visualization.DataView(data);
        view.setColumns([0, 1, 2, 3, 4, 5, 6, {
          calc: function (dt, row) {
            var answered = 0;
            var q1_1 = dt.getValue(row, 3) || '';
            var q1_2 = dt.getValue(row, 4) || '';
            var q1_3 = dt.getValue(row, 5) || '';
            var q1_4 = dt.getValue(row, 6) || '';
            if ((q1_1 !== '') || (q1_2 !== '') || (q1_3 !== '') || (q1_4 !== '')) {
              answered = 1;
            }
            return answered;
          },
          label: 'Answered',
          type: 'number'
        }]);
    
        var totalAnswered = google.visualization.data.group(
          view,
          [{column: 0, type: 'string', modifier: function () {return 'Total';}}],
          [{
            column: view.getNumberOfColumns() - 1,
            type: 'number',
            label: view.getColumnLabel(view.getNumberOfColumns() - 1),
            aggregation: google.visualization.data.sum
          }]
        );
    
        var proxyTable = new google.visualization.ChartWrapper({
          chartType: 'Table',
          containerId: 'proxyTable',
          dataTable: view
        });
        proxyTable.draw();
    
        document.getElementById('proxyTableTotal').innerHTML = 'Total Answered = ' + totalAnswered.getValue(0, 1);
      }
    }
    <script src="https://www.gstatic.com/charts/loader.js"></script>
    <div id="proxyTable"></div>
    <div id="proxyTableTotal"></div>

    【讨论】:

    • 哇,谢谢!你真的是英雄!我对此感到非常困惑,但您的回答帮助澄清了很多事情!再多一点帮助 - 你能告诉我如何使用百分比(总变量)而不是计数来绘制图表吗?而且我还注意到,如果您选择过滤器卡 4 和活动 2 - 没有已解决的案例,因此图表仅绘制两个条形图,并且没有为已解决类别绘制“零”值条形图 - 是否有任何方法可以显示这一点如果为零?
    • 嗨@WhiteHat - 我有一个后续问题。使用您提供的方法,解决方案完美运行,但我在分析多项选择问题时陷入困境 - 基本上这些是您可以选择的复选框问题不止一个答案,因此数据存在于多个列中。我在这张表上创建了一些示例数据:docs.google.com/spreadsheets/d/…。这些列集的总计将如何完成(此问题的总数应为 8)-您可以在这里提供任何帮助吗?
    • 哇,太棒了!!!我必须使用这个总数创建一个类似于早期图表的图表,但让我尝试在图表中使用这个“已回答”列。我无法表达我对你的感激之情,你真的是谷歌可视化方面的专家!!!
    • 我想我说得太早了,我尝试创建一个新视图 (view2) 并尝试根据这个新视图 2(它具有列 3、4、5、6 和 TotalAnswered)绘制图表,但是我收到错误。所以不允许我在这里粘贴我的代码,所以将我的代码粘贴在电子表格 docs.google.com/spreadsheets/d/… 的表 2 中。基本上我想使用总数创建一个条形图,其中第一季度每列的“是”百分比(所以第一个条形图有 50%,即 4/8。第二个条形图应该是 37.5,即 3/8,依此类推.. . 请你再帮我一次。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 2022-08-20
    • 2022-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多