【问题标题】:Google Chart using Control Wrapper for Multiple Choice QuestionsGoogle Chart 使用 Control Wrapper 解决多项选择问题
【发布时间】:2017-09-11 23:29:28
【问题描述】:

我有多项选择(复选框)问题的数据 - 数据的结构使得人们可以选择无、一个或多个选项,因此数据保存在多个列中。我正在尝试使用控制包装器构建一个谷歌图表,以便它可以过滤,但同时我想使用百分比而不是计数来绘制数据图表。这就是棘手的部分,因为基数(或分母)将是回答问题的总人数而不是文件中活动行的总数.. 所以在我的数据中,基数/分母是 8(因为只有 8 人回答了这个问题,2 人将其留空/未回答)我希望每列中每个是的计数除以 8,以便计算每个选项的百分比,然后在一个条形图中绘制所有选项。数据在此电子表格中: https://docs.google.com/spreadsheets/d/19VWNZkHG5GEuYCibDmtOlKblKiOWcx94Wi9jyuhvEUo/edit#gid=0

我还将所需的输出图表保存在同一张表中。 @WhiteHat 帮助我在数据视图中汇总数据(我非常感谢他在这里指导我朝着正确的方向前进!!!)但是当我创建一个包含所需列的新数据视图时,我的图表没有绘制 - 我收到错误消息“给定轴上的所有系列必须具有相同的数据类型”。

到目前为止我的代码是:

    <!DOCTYPE html>

    <html>
      <head>
        <base target="_top">
    <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
    <script src="https://www.gstatic.com/charts/loader.js"></script>






      <script type="text/javascript">

    function drawVisualization() {
      var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/19VWNZkHG5GEuYCibDmtOlKblKiOWcx94Wi9jyuhvEUo/edit?gid=0&range=A:H');
      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': true
            }
          }
        });

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

        // Define a bar chart to show 'Population' data
        var barChart = new google.visualization.ChartWrapper({
          'chartType': 'ColumnChart',
          'containerId': 'chart1',
          'options': options_Column
        });


        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);


        // 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();



        var view2 = new google.visualization.DataView(proxyTable);
        view.setColumns([3, 4, 5, 6, {
            calc: function (dt, row) {
              var amount =  dt.getValue(row, 1);

              var percent = 0;
              if (totalAnswered.getValue(0, 1) > 0) {
                percent = amount / totalAnswered.getValue(0, 1);
              }
              return {
                v: percent,
                f: formatPercent.formatValue(percent)
              };
            },
            type: 'number',
            label: 'Percent'
          }, {
            calc: function (dt, row) {
              var amount =  dt.getValue(row, 1);
              var percent = 0;
              if (totalAnswered.getValue(0, 1) > 0) {
                percent = amount / totalAnswered.getValue(0, 1);
              }
              return 'N=' + 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(view2);
          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" ></div>
                <div id="proxyTableTotal" ></div>
            </div>

            </body>  
            </html>

提前感谢您的帮助!!!

【问题讨论】:

    标签: javascript charts google-visualization


    【解决方案1】:

    要获得每列的“是”计数,
    我们可以将这些列包含在我们的聚合中,
    创建视图后

    这里使用了一个自定义的 agg 函数来计算“是”值 --> countYes

    然后创建一个新的数据表,
    将每个计数列添加为一行,
    占总回答的百分比

    请参阅以下工作 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&range=A:H');
      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': true
            }
          }
        });
    
        var Campaign = new google.visualization.ControlWrapper({
          'controlType': 'CategoryFilter',
          'containerId': 'control2',
          'options': {
            'filterColumnLabel': 'Campaign Filter',
            'ui': {
              'labelStacking': 'vertical',
              'allowTyping': false,
              'allowMultiple': true
            }
          }
        });
    
        // Define a bar chart to show 'Population' data
        var barChart = new google.visualization.ChartWrapper({
          'chartType': 'ColumnChart',
          'containerId': 'chart1'
        });
    
        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: [1]
          }
        });
    
        // 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();
    
          // build view with calc for answered
          var view = new google.visualization.DataView(dataTable);
          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'
          }]);
    
          // build agg columns for each choice and answered
          var aggColumns = [];
          for (var i = 3; i < view.getNumberOfColumns(); i++) {
            var aggFunc;
            if (i < (view.getNumberOfColumns() - 1)) {
              aggFunc = countYes;
            } else {
              aggFunc = google.visualization.data.sum;
            }
    
            aggColumns.push({
              column: i,
              type: 'number',
              label: view.getColumnLabel(i),
              aggregation: aggFunc
            });
          }
    
          // function to count yes values
          function countYes(values) {
            var yes = 0;
            values.forEach(function (value) {
              if (value === 'Yes') {
                yes++;
              }
            });
            return yes;
          }
    
          // aggregate view
          var totalAnswered = google.visualization.data.group(
            view,
            [{column: 0, type: 'string', modifier: function () {return 'Total';}}],
            aggColumns
          );
    
          // data table for bar chart
          var choiceData = new google.visualization.DataTable();
          choiceData.addColumn('string', 'Choice');
          choiceData.addColumn('number', 'Percent');
          choiceData.addColumn({role: 'annotation', type: 'string'});
    
          // add row for each column in aggregation
          for (var i = 1; i < totalAnswered.getNumberOfColumns() - 1; i++) {
            var value = totalAnswered.getValue(0, i);
            var total = totalAnswered.getValue(0, totalAnswered.getNumberOfColumns() - 1);
            var percent = 0;
            if (total > 0) {
              percent = value / total;
            }
            choiceData.addRow([
              totalAnswered.getColumnLabel(i),
              {
                v: percent,
                f: formatPercent.formatValue(percent)
              },
              formatPercent.formatValue(percent) + ' (' + formatShort.formatValue(value) + ')'
            ]);
          }
    
          barChart.setDataTable(choiceData);
          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="dashboard"></div>
    <div id="control1"></div>
    <div id="control2"></div>
    <div id="chart1"></div>
    <div id="proxyTable"></div>
    <div id="proxyTableTotal"></div>

    【讨论】:

    • 这正是我想要的。非常感谢你。我觉得你是谷歌可视化和图表包装方法的顶级专家,如果在这个领域有任何奖项,那绝对应该给你!!非常感谢!!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多