Гистограмма Google с процентами от общего количества и с фильтрами категорий

1

Я новичок в Google Charts и пытался создать гистограмму с% от общей суммы, а также возможность фильтровать данные с помощью элементов управления Dashboard Google... Я следил за этим (спасибо @asgallant за это!) Google. visualization.ChartWrapper Group Columns View и смог получить гистограмму, которая собирает данные с листа Google, и рисует диаграмму с подсчетами, а также имеет возможность фильтровать данные с помощью фильтров категории Google.

Тем не менее, это то место, где я застрял - когда я пытаюсь добавить другие столбцы (dataview) для вычисления общего количества (чтобы я мог рисовать диаграмму с использованием процента, а также показывать процентное соотношение в метках бара) - моя диаграмма все еще рисует используя подсчеты. Может кто-нибудь, пожалуйста, дайте мне знать, что я здесь не так:

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 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>
Теги:
charts
bar-chart
google-visualization

1 ответ

1
Лучший ответ

для начинающих рекомендуем использовать новую библиотеку loader.js

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

вместо jsapi, в соответствии с примечаниями к выпуску...

Версия Google Charts, которая остается доступной через загрузчик jsapi не обновляется постоянно. С этого момента вы можете использовать новый gstatic loader.

это изменит только оператор load, см. следующий рабочий фрагмент...


следующий, не видел определения для числа форматировщиков
formatShort и formatPercent
необходимо добавить эти


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

наконец, удалите параметр view из barChart
поскольку мы предоставляем view мы хотим сделать


см. следующий рабочий фрагмент...

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

см. следующий рабочий фрагмент...

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

чтобы найти общее количество вопросов с множественным выбором,
создать представление с вычисленным столбцом
новый столбец должен проверить, что все столбцы вопросов не пусты
затем общее представление на расчетной колонке

см. следующий рабочий фрагмент...

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>
  • 0
    Вау, спасибо за это! Вы действительно герой! Я так запутался с этим, но ваш ответ помог многое прояснить !!! Еще одна помощь - Можете ли вы также дать мне знать, как нарисовать график, используя процент (общая переменная) вместо количества? И я также заметил, что если вы выберете фильтры «Карта 4» и «Кампания 2» - нет разрешенных случаев, поэтому диаграмма отображает только два столбца и не отображает столбец «нулевого значения» для категории «Разрешенные» - есть ли способ показать это даже если его ноль?
  • 0
    см. ОБНОВЛЕНИЕ выше ...
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню