Панель инструментов линейной диаграммы с агрегированными точками данных - PullRequest
0 голосов
/ 15 ноября 2018

Я работаю над панелью мониторинга, содержащей линейную диаграмму, табличную диаграмму и два фильтра категорий, и мне нужно выяснить, как объединить несколько строк в точки, которые могут быть нанесены на линейную диаграмму.

Учитывая набор данных, содержащийся в листе Google, например, приведенный ниже образец I, на линейном графике должны отображаться годы по оси X (2014–2017 годы) и среднее значение всех показателей удовлетворенности для обеих компаний и всех ведомства.

Первый CategoryFilter позволяет пользователю выбрать одну из компаний. Когда они выбирают один, линейный график должен показывать совокупные номера всех отделов, вместе взятых.

Второй CategoryFilter позволяет пользователю выбрать отдел, а линейный график должен показывать уровень удовлетворенности для этой отдельной компании / отдела.

В нынешнем виде, после того, как я "углублюсь" в отдельную компанию / отдел, график отображается правильно. На данный момент моя задача состоит в том, чтобы заставить работать агрегации до тех пор, пока фильтры двух категорий не будут использованы для "детализации" до одного отдела.

Кто-нибудь может указать мне на ресурс, который описывает, как это сделать, или на рабочий пример, который я вижу, как его кодировать?

Company    Department    Year    Satisfaction_Rate
CompA      Personnel     2014    0.8542
CompA      Personnel     2015    0.8680
CompA      Personnel     2016    0.8712
CompA      Personnel     2017    0.8832
CompA      Sales         2014    0.7542
CompA      Sales         2015    0.7680
CompA      Sales         2016    0.7712
CompA      Sales         2017    0.7832
CompA      Labor         2014    0.6542
CompA      Labor         2015    0.6680
CompA      Labor         2016    0.6712
CompA      Labor         2017    0.6832
CompB      Personnel     2014    0.9242
CompB      Personnel     2015    0.9280
CompB      Personnel     2016    0.9312
CompB      Personnel     2017    0.9132
CompB      Sales         2014    0.8742
CompB      Sales         2015    0.8880
CompB      Sales         2016    0.8112
CompB      Sales         2017    0.8632
CompB      Labor         2014    0.7942
CompB      Labor         2015    0.8080
CompB      Labor         2016    0.8112
CompB      Labor         2017    0.8232

Хотя этот пример данных точно отражает концепцию типа данных, с которыми я работаю, фактические данные совершенно иные, как вы заметите в моем коде.

// Load the Visualization API and the corechart package.
google.charts.load('current', { 'packages': ['corechart', 'controls'] });

// Set a callback to run when the Google Visualization API is loaded.
google.charts.setOnLoadCallback(drawCharts);

//------------------------------------------------------------------------------

function GetDataFromSheet(URL, queryString, callback) {
    var query = new google.visualization.Query(URL);
    query.setQuery(queryString);
    query.send(gotResponse);

    function gotResponse(response) {
        if (response.isError()) {
            console.log(response.getReasons());
            alert('Error in query: ' + response.getMessage() + " " + response.getDetailedMessage());
            return;
        }
        if (response.hasWarning()) {
            console.log(response.getReasons());
            alert('Warning from query: ' + response.getMessage() + " " + response.getDetailedMessage());
            return;
        }
        callback(response);
    }
}

//------------------------------------------------------------------------------

function drawCharts() {
    var URL, query;

    // PREP DATA SOURCE
    URL = 'https://docs.google.com/spreadsheets/d/1QygNPsYR041jat.../gviz/tq?gid=1339946796';
    query = 'select A, C, D, H, J, M, P, S LABEL A "AEA", C "District", D "Class of", H "Graduation Rate", J "Post-Secondary Intention Rate", M "Enrollment Rate", P "Persistence Rate", S "Completion Rate"';
    GetDataFromSheet(URL, query, handlePrep);

}



//------------------------------------------------------------------------------
// POST SECONDARY READINESS & EQUITY PARTNERSHIP

function handlePrep(response) {

    var data = response.getDataTable();

    // Attempting to aggregate...  grouping on index 2, "class of". Example: 2015
    //   averaging column 3, Graduation Rate
    var result = google.visualization.data.group(
        data,
        [2],
        [{'column': 3, 'aggregation': google.visualization.data.avg, 'type': 'number'}]
    );

    var container = new google.visualization.Dashboard(document.getElementById('divPrep'));

    var AEAControl = new google.visualization.ControlWrapper({
        controlType: 'CategoryFilter',
        containerId: 'divAEAPicker',
        options: {
            filterColumnIndex: 0,
            ui: {
                selectedValuesLayout: 'belowStacked',
                label: 'AEA Selector ->',
                caption: 'Choose an AEA...',
                allowNone: true,
                allowMultiple: false
            },
        }
    });

    var DistrictControl = new google.visualization.ControlWrapper({
        controlType: 'CategoryFilter',
        containerId: 'divDistrictPicker',
        options: {
            filterColumnIndex: 1,
            ui: {
                label: 'District Selector ->',
                caption: 'Choose a District...',
                allowNone: true,
                allowMultiple: false
            },
        }
    });

    var chart = new google.visualization.ChartWrapper({
        chartType: 'LineChart',
        containerId: 'divPrepChart',
        options: {
            height: 400,
            width: 1200,
            pointSize: 5,
            title: 'Post-Secondary Readiness & Equity Partnership (PREP) Trendlines',
            legend: { position: 'top', maxLines: 3 },
            //chartArea: { left: '10%', width: '85%'},
            tooltip:{textStyle: {color: '#000000'}, showColorCode: true},
            hAxis:{
                format: 'yyyy',
                title: 'Graduating Class Year'
            },
            vAxis: {
                format: 'percent',
                maxValue: 1,
                minValue: 0
            }
        },
        view: {'columns': [2, 3, 4, 5, 6, 7]}
    });

    var table = new google.visualization.ChartWrapper({
        chartType: 'Table',
        containerId: 'divTable',
        options: {
            title: 'Post-Secondary Readiness & Equity Partnership ',
            legend: { position: 'top', maxLines: 3 },
            //chartArea: { left: '10%', width: '85%'},
            page: 'enable',
            pageSize: 10


        }
    });

    // Create a formatter to display values as percent
    var percentFormatter = new google.visualization.NumberFormat({pattern: '0.00%'});
    percentFormatter.format(data, 3);
    percentFormatter.format(data, 4);
    percentFormatter.format(data, 5);
    percentFormatter.format(data, 6);
    percentFormatter.format(data, 7);


    // Configure the controls so that:
    // - the AEA selection drives the District one
    // - both the AEA and Disctirct selections drive the linechart
    // - both the AEA and Districts selections drive the table
    container.bind(AEAControl, DistrictControl);
    container.bind([AEAControl, DistrictControl], [chart, table]);

    // Draw the dashboard named 'container'
    container.draw(data);

    // Until we figure out how to display aggregated values at the AEA and State levels,
    // keep the line graph hidden until both an AEA and District are chosen from the category filters
    google.visualization.events.addListener(container, 'ready', function() {
        var aeaSelectedValues = AEAControl.getState()['selectedValues'];
        var districtSelectedValues = DistrictControl.getState()['selectedValues'];
        if (aeaSelectedValues.length == 0 || districtSelectedValues.length == 0) {
            document.getElementById('divPrepChart').style.visibility = 'hidden';
         } else {
            document.getElementById('divPrepChart').style.visibility = 'visible';
         }
    });

}

Вот как мои данные в настоящее время отображаются на графике до параметров, выбранных с помощью фильтров категории ... Ugly Chart - not aggregated

Мне нужно, чтобы это выглядело примерно так ... Nice Chart

1 Ответ

0 голосов
/ 15 ноября 2018

вам нужно будет нарисовать элементы управления и диаграммы независимо, без использования приборной панели.
затем вы можете нарисовать диаграммы, когда сработает событие 'statechage' элемента управления.
когда сработает событие, вы можете агрегировать данныена основе выбранных значений,
и перерисовать графики.

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

google.charts.load('current', { 'packages': ['corechart', 'controls'] });
google.charts.setOnLoadCallback(handlePrep);

function handlePrep(response) {
    var data = google.visualization.arrayToDataTable([
      ['Company',    'Department',    'Year',    'Satisfaction_Rate'],
      ['CompA',      'Personnel',     2014,    0.8542],
      ['CompA',      'Personnel',     2015,    0.8680],
      ['CompA',      'Personnel',     2016,    0.8712],
      ['CompA',      'Personnel',     2017,    0.8832],
      ['CompA',      'Sales',         2014,    0.7542],
      ['CompA',      'Sales',         2015,    0.7680],
      ['CompA',      'Sales',         2016,    0.7712],
      ['CompA',      'Sales',         2017,    0.7832],
      ['CompA',      'Labor',         2014,    0.6542],
      ['CompA',      'Labor',         2015,    0.6680],
      ['CompA',      'Labor',         2016,    0.6712],
      ['CompA',      'Labor',         2017,    0.6832],
      ['CompB',      'Personnel',     2014,    0.9242],
      ['CompB',      'Personnel',     2015,    0.9280],
      ['CompB',      'Personnel',     2016,    0.9312],
      ['CompB',      'Personnel',     2017,    0.9132],
      ['CompB',      'Sales',         2014,    0.8742],
      ['CompB',      'Sales',         2015,    0.8880],
      ['CompB',      'Sales',         2016,    0.8112],
      ['CompB',      'Sales',         2017,    0.8632],
      ['CompB',      'Labor',         2014,    0.7942],
      ['CompB',      'Labor',         2015,    0.8080],
      ['CompB',      'Labor',         2016,    0.8112],
      ['CompB',      'Labor',         2017,    0.8232],
    ]);

    var AEAControl = new google.visualization.ControlWrapper({
        controlType: 'CategoryFilter',
        containerId: 'divAEAPicker',
        dataTable: data,
        options: {
            filterColumnIndex: 0,
            ui: {
                selectedValuesLayout: 'belowStacked',
                label: 'AEA Selector ->',
                caption: 'Choose an AEA...',
                allowNone: true,
                allowMultiple: false
            },
        }
    });

    var DistrictControl = new google.visualization.ControlWrapper({
        controlType: 'CategoryFilter',
        containerId: 'divDistrictPicker',
        dataTable: data,
        options: {
            filterColumnIndex: 1,
            ui: {
                label: 'District Selector ->',
                caption: 'Choose a District...',
                allowNone: true,
                allowMultiple: false
            },
        }
    });

    var chart = new google.visualization.ChartWrapper({
        chartType: 'LineChart',
        containerId: 'divPrepChart',
        options: {
            height: 400,
            width: 1200,
            pointSize: 5,
            title: 'Post-Secondary Readiness & Equity Partnership (PREP) Trendlines',
            legend: { position: 'top', maxLines: 3 },
            tooltip:{textStyle: {color: '#000000'}, showColorCode: true},
            hAxis:{
                format: '0',
                title: 'Graduating Class Year'
            },
            vAxis: {
                format: 'percent',
                maxValue: 1,
                minValue: 0
            }
        },
    });

    var table = new google.visualization.ChartWrapper({
        chartType: 'Table',
        containerId: 'divTable',
        options: {
            title: 'Post-Secondary Readiness & Equity Partnership ',
            legend: { position: 'top', maxLines: 3 },
            page: 'enable',
            pageSize: 10


        }
    });

    google.visualization.events.addListener(AEAControl, 'statechange', drawDashboard);
    google.visualization.events.addListener(DistrictControl, 'statechange', drawDashboard);

    function drawDashboard() {
      var view = new google.visualization.DataView(data);
      var valuesAEA = AEAControl.getState();
      var valuesDistrict = DistrictControl.getState();
      var viewRows = [];

      if (valuesAEA.selectedValues.length > 0) {
        viewRows.push({
          column: AEAControl.getOption('filterColumnIndex'),
          test: function (value) {
            return (valuesAEA.selectedValues.indexOf(value) > -1);
          }
        });
      }
      if (valuesDistrict.selectedValues.length > 0) {
        viewRows.push({
          column: DistrictControl.getOption('filterColumnIndex'),
          test: function (value) {
            return (valuesDistrict.selectedValues.indexOf(value) > -1);
          }
        });
      }
      if (viewRows.length > 0) {
        view.setRows(data.getFilteredRows(viewRows));
      }
      result = google.visualization.data.group(
        view,
        [2],
        [{'column': 3, 'aggregation': google.visualization.data.avg, 'type': 'number'}]
      );
      var percentFormatter = new google.visualization.NumberFormat({pattern: '0.00%'});
      percentFormatter.format(result, 1);

      chart.setDataTable(result);
      chart.draw();
      table.setDataTable(result);
      table.draw();
    }

    AEAControl.draw();
    DistrictControl.draw();
    drawDashboard();
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="divPrep">
  <div id="divAEAPicker"></div>
  <div id="divDistrictPicker"></div>
  <div id="divPrepChart"></div>
  <div id="divTable"></div>
</div>
...