У меня есть данные для вопроса с множественным выбором (checkboxes) - данные структурированы таким образом, что человек может выбрать ни один, один или несколько параметров, поэтому данные сохраняются в нескольких столбцах. Я пытаюсь создать диаграмму google, используя контрольные оболочки, чтобы ее можно было фильтровать, но в то же время я хочу отображать данные, используя процент, а не счетчик.. И это сложная часть, потому что базовый (или знаменатель) будет общее число людей, отвечающих на вопрос, а не общее количество активных строк в файле.. поэтому в моих данных базовый/знаменатель равен 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 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>
Спасибо за любую помощь заранее!
для подсчета "Да" для каждого столбца,
мы можем включить эти столбцы в нашу агрегацию,
после создания представления
здесь пользовательская функция agg используется для подсчета значений "Да" → countYes
то создается новая таблица данных,
с каждым столбцом счетчика, добавленным как строка,
с процентом от общего количества ответов
см. следующий рабочий фрагмент...
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 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>