I'm trying to draw a line chart from a data table. This should be quite simple. The line chart draws just fine until I try to access a column further down the spreadsheet.
When I draw the data table for the second column like this I get an awesome linegraph:
var costsTable = new google.visualization.DataTable();
costsTable.addColumn('number', 'colIndex');
costsTable.addColumn('string', 'colLabel');
costsTable.addRow([0, data1.getColumnLabel(0)]); //month
costsTable.addRow([2, data1.getColumnLabel(2)]); //costs
BUT when I replace the second row with the sixth row:
costsTable.addRow([6, data1.getColumnLabel(6)]); //consumption
I get this error:
> Invalid row index undefined. Should be in the range [0-1].
I don't understand what is causing this error because I put in 2 as the index and it works just fine.
If I replace the second row with
costsColumnsTable.addRow([1, data3.getColumnLabel(2)]); //costs
I get the error:
> Data column(s) for axis #0 cannot be of type string
This doesn't make sense to me how the line graph can be drawn perfectly with an index of 2, but not six.
I've logged the values of the working dataTable, and it is indeed assigning the given indexes and receiving the specified column label.
The dataTable looks like:
0, Month
2, Amount Billed
Which are my chosen indexes and labels. However, I cannot do this with another index.
Here's my entire chart function:
function drawElectricalLine(data3){
var linechartCost = new google.visualization.ChartWrapper({
'chartType': 'LineChart',
'containerId': 'line_chart',
dataTable: data3,
options: {
animation:{
duration: 1000,
easing: 'out',
},
width: 800,
height: 400,
title: 'Monthly Electric Costs',
explorer: {},
hAxis: {
title: 'Date'
},
vAxis: {
title: 'Amount Billed ($)'
//' Consumption (kWh)'
}
}
});
var initState= {selectedValues: []};
var costsColumnsTable = new google.visualization.DataTable();
costsColumnsTable.addColumn('number', 'colIndex');
costsColumnsTable.addColumn('string', 'colLabel');
costsColumnsTable.addRow([0, data3.getColumnLabel(0)]); //month
costsColumnsTable.addRow([2, data3.getColumnLabel(2)]); //costs
//costsColumnsTable.addRow([6, data3.getColumnLabel(6)]); //costs ---> causes error
initState.selectedValues.push(data3.getColumnLabel(2));
var columnFilter = new google.visualization.ControlWrapper({
controlType: 'CategoryFilter',
containerId: 'electrical_selector',
dataTable: costsColumnsTable,
options: {
filterColumnLabel: 'colLabel',
ui: {
label: '',
caption: 'Consumption',
allowTyping: false,
allowMultiple: true,
allowNone: false
}
},
state: initState
});
setChartView(linechartCost, costsColumnsTable, columnFilter);
}//end drawElectricalLine
function setChartView(linechart, columnsTable, columnFilter) {
var state = columnFilter.getState();
var row;
var view = {
columns: [0]
};
for (var i = 0; i < state.selectedValues.length; i++) {
row = columnsTable.getFilteredRows([{column: 1, value: state.selectedValues[i]}])[0];
view.columns.push(columnsTable.getValue(row, 0));
}
// sort the indices into their original order
view.columns.sort(function (a, b) {
return (a - b);
});
linechart.setView(view);
linechart.draw();
}
All I'm trying to do is draw a basic line chart from my month column data1.getColumnLabel(0) and my consumption column data1.getColumnLabel(6)
And I do not see why I cannot assign a different index without getting an error.
UPDATE:
I fixed the first column to be type string. My data1.getColumnLabel(0) is not even in index 1 :(
Related
I want to populate data_results which is a DataTable from three data views most likely a serial manner. I do not know the syntax to do this.
I've tried using .addRow() and .addRows() but can't seem to get the syntax correct when trying the final append to data_results.
See my simplistic example below.
Some givens:
I would like to produce a data table called data_results.
It will have 3 columns (Final1, Final2, Final3).
I would like to know how to take rows from view_A, view_B, and view_C and append them to data_results.
As always, your expert assistance is appreciated!
This snippet has been edited per #WhiteHat's suggestions to producce the final solution.
google.charts.load('current', {
'packages': ['corechart', 'table', 'controls']
});
renderChart_onPageLoad();
function renderChart_onPageLoad() {
google.charts.setOnLoadCallback(function() {
drawTable();
}); //END setOnLoadCallback
} //END function renderChart_onEvent
function drawTable() {
var data_A = new google.visualization.DataTable();
data_A.addColumn('string', 'A1');
data_A.addColumn('string', 'A2');
data_A.addColumn('number', 'A3');
data_A.addRow(['X', 'Y', 1]);
var data_B = new google.visualization.DataTable();
data_B.addColumn('string', 'B1');
data_B.addColumn('string', 'B2');
data_B.addColumn('number', 'B3');
data_B.addRow(['XX', 'YY', 2]);
var data_C = new google.visualization.DataTable();
data_C.addColumn('string', 'C1');
data_C.addColumn('string', 'C2');
data_C.addColumn('number', 'C3');
data_C.addRow(['XXX', 'YYY', 3])
var view_A = new google.visualization.DataView(data_A);
var view_B = new google.visualization.DataView(data_B);
var view_C = new google.visualization.DataView(data_C);
var data_results_join1 = google.visualization.data.join(view_A, view_B, 'full',
[[0, 0],[1, 1],[2, 2]], '', '');
var data_results = google.visualization.data.join(data_results_join1, view_C, 'full',
[[0, 0],[1, 1],[2, 2]], '', '');
var dashboard = new google.visualization.Dashboard(document.getElementById('div_dashboard'));
var categoryPicker1 = new google.visualization.ControlWrapper({
'controlType': 'StringFilter',
'containerId': 'div_categoryPicker1',
'matchType': 'any',
'options': {
'filterColumnIndex': 0, //Column used in control
'ui': {
//'label': 'Is exclude selection possible?',
//'labelSeparator': ':',
'labelStacking': 'vertical',
'selectedValuesLayout': 'belowWrapping',
'allowTyping': false,
'allowMultiple': false,
'allowNone': true
}
}
});
var table = new google.visualization.ChartWrapper({
chartType: 'Table',
containerId: 'div_table',
options: {
allowHtml: true
}
});
dashboard.bind([categoryPicker1], [table]);
dashboard.draw(data_results);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id='div_dashboard'>
<div id='div_categoryPicker1'></div><br/>
<div id='div_table'></div>
</div>
When researching this task I also found this to work.
var data_results = new google.visualization.DataTable();
data_results.addColumn('string', 'FinalC1');
data_results.addColumn('string', 'FinalC2');
data_results.addColumn('number', 'FinalC3');
function addRowsToDataResult(sourceView, c1, c2, c3) {
for (var i = 0; i < sourceView.getNumberOfRows(); i++) {
var col1 = sourceView.getValue(i, sourceView.getColumnIndex(c1));
var col2 = sourceView.getValue(i, sourceView.getColumnIndex(c2));
var col3 = sourceView.getValue(i, sourceView.getColumnIndex(c3));
data_results.addRow([col1, col2, col3]);
}
}
addRowsToDataResult(view_A, 'A1', 'A2', 'A3');
addRowsToDataResult(view_B, 'B1', 'B2', 'B3');
addRowsToDataResult(view_C, 'C1', 'C2', 'C3');
Thank you to #WhiteHat! Cheers...
Comment:
need to use the join method -- two times -- first to join the first two tables, and again to join the third table to the result of the first join -- here is an example of how to use the join method – WhiteHat Oct 3 at 19:34
This was the answer. Original post modified to reflect the suggestion. Thank you #WhiteHat
I have been fiddling with a particle photon, posting data to sparkfun.com
To display this data I am trying to use google.visualization. But I cant seem to get the axis behaving as I want it to.
see (but wait a while it is slow): https://www.hanscees.com/photon/charts-data-sparkfunA.html
I want the caxis to show not 1K, but 1010 and so on. here is my code:
function drawChart1() {
var public_key = 'yA0EjKV3owhKNx1NlN3w';
// JSONP request
var jsonData = $.ajax({
url: 'https://data.sparkfun.com/output/' + public_key + '.json',
//data: {page: 1},
data: {'lte' : {'timestamp' : 'now - 4 hours'}},
dataType: 'jsonp',
}).done(function (results) {
var data = new google.visualization.DataTable();
data.addColumn('datetime', 'Time');
data.addColumn('number', 'Pressure');
$.each(results, function (i, row) {
data.addRow([
(new Date(row.timestamp)),
parseFloat(row.hectopascals)
]);
}); // each row
// see https://google-developers.appspot.com/chart/interactive/docs/gallery/linechart#dual-y-charts
var materialOptions = {
chart: { title: 'Barometer Pressure'},
width: 550,
height: 500,
series: {
// Gives each series an axis name that matches the Y-axis below.
0: {axis: 'Pressure'}
},
axes: {
// Adds labels to each axis; they don't have to match the axis names.
y: {
Pressure: {label: 'Pressure (Hpa)'}
}
},
vAxis: {format: 'decimal'},
hAxis: {color: '#333', count: 8}
};
var materialChart = new google.charts.Line(ChartDivBaro);
materialChart.draw(data, materialOptions);
}); // results
} // jsondata
unfortunately, most vAxis options simply do not work on material charts...
see --> Tracking Issue for Material Chart Feature Parity #2143
recommend using a core chart instead...
you can use the following option to get the look and feel close to material
theme: 'material'
solved it without material:
var options = {title:'Pressure Outside',
width:550,
height:300,
vAxis: {format: '0'}
};
var chart = new google.visualization.LineChart($('#chart1').get(0));
chart.draw(data, options); // draw data
}); // results
i use the ChartWrapper from google charts.. my actual implementation looks like this:
var dataTable=new google.visualization.DataTable(DATA);
var options = {
title: 'Name of the Chart',
vAxis: {title: "Cups"},
hAxis: {title: "Month"},
isStacked: false,
pointSize: 3
};
var chartWrapperArgs = {
chartType: "LineChart",
dataTable: dataTable,
view: {"columns":[0,1,2]},
options: options,
containerId: "chart"]
};
var chartWrapper = new google.visualization.ChartWrapper(chartWrapperArgs);
chartWrapper.draw();
the problem is, sometimes i must change the data type from "date" to "string" i do this in my old implementation(there is no ChartWrapper) like this:
var dataView = new google.visualization.DataView(dataTable);
dataView.setColumns([{
type: 'string',
label: dataView.getColumnLabel(0),
calc: function (dt, row) {
return dt.getFormattedValue(row, 0);
}
}, 1]);
this works and now i have tried the same with my ChartWrapper implementation but with no success:
i have tried this two approaches:
1.)
var dataTable=new google.visualization.DataTable(DATA);
var chartWrapperArgs = {
chartType: "LineChart",
dataTable: dataTable,
view: {"columns":[
{
type: 'string',
label: dataTable.getColumnLabel(0),
calc: function (dt, row) {
return dt.getFormattedValue(row, 0);
}
},
1
]},
options: options,
containerId: "chart"]
};
var chartWrapper = new google.visualization.ChartWrapper(chartWrapperArgs);
and my second:
var dataTable=new google.visualization.DataTable(DATA);
var dataView = new google.visualization.DataView(dataTable);
dataView.setColumns([{
type: 'string',
label: dataView.getColumnLabel(0),
calc: function (dt, row) {
return dt.getFormattedValue(row, 0);
}
}, 1]);
var ViewData= dataView.toJSON();
var chartWrapperArgs = {
chartType: "LineChart",
dataTable: dataTable,
view: ViewData,
options: options,
containerId: "chart"]
};
var chartWrapper = new google.visualization.ChartWrapper(chartWrapperArgs);
but this did also not worked..
what do i wrong ?
i know i can set the view directly to the dataTable like "dataTable : view" but i want only do this in the "view:" option or the chartWrapper.setView() option.. or is this not possible ?
Your first method (setting the view parameter) should work, but your code had a syntax error at the end of the containerId: "chart"] line (the ] should not be there):
var chartWrapperArgs = {
chartType: "LineChart",
dataTable: dataTable,
view: {
columns: [{
type: 'string',
label: dataTable.getColumnLabel(0),
calc: function (dt, row) {
return dt.getFormattedValue(row, 0);
}
}, 1]
},
options: options,
containerId: "chart"
};
var chartWrapper = new google.visualization.ChartWrapper(chartWrapperArgs);
If that isn't working, can you post a full example demonstrating the problem?
I'm trying to perform a fairly basic procedure. I have a lengthy data table with large cell sizes to use with Google Visualization. Before creating the page I'd like to replace the large cells with codes and abbreviations to keep the file sizes and loading times down. I can handle that. However, when a cell or column value/name/label shows up in the visualization itself I'd like to see a longform version of the value (ex. 'Male' in original dataset -> 'M' in Google Visualization data table -> 'Male' in category filter dropdown, tooltip, etc.), and this has been unexpectedly problematic.
I've tried to replicate the issue (and my failed attempt to fix it) in the modified Google Playground example below. In this example I've changed the initial dataset to have 'M' and 'F' in the Gender column, and I still want the visualization to display 'Male' and 'Female' in the dropdown and the displayed table as it does in the original visualization.
My attempt to fix is labeled ATTEMPT TO FIX GENDER below; basically, I'm trying to create a DataView of the original table and replace the Gender column with a calculated column transforming the 'M's and 'F's into 'Male's and 'Female's...but I'm not sure if this is a wise approach, even if I could get it to work (which I can't). The point of this runaround is to avoid replacing every short value in the original table with a long one; I only want to replace table values as they are being displayed in the visualization. But I can't find another approach here or elsewhere, and I'm a bit new to this stuff so I don't think I can come up with one without some guidance. At least, not if the past several hours of failure are any indication.
Any advice or suggestions would be sorely appreciated. The original code example is here.
function drawVisualization() {
// Prepare the data
var data = new google.visualization.DataTable();
data.addColumn('string', 'Name');
data.addColumn('string', 'Gender');
data.addColumn('number', 'Age');
data.addColumn('number', 'Donuts Eaten');
data.addRows([
['Michael' , 'M', 12, 5],
['Elisa', 'F', 20, 7],
['Robert', 'M', 7, 3],
['John', 'M', 54, 2],
['Jessica', 'F', 22, 6],
['Aaron', 'M', 3, 1],
['Margareth', 'F', 42, 8],
['Miranda', 'F', 33, 6]
]);
*******//ATTEMPT TO FIX GENDER
/*var sexfix = function (data, row) {
var val = data.getValue(row, 1);
switch (val) {
case 'M':
val = 'Male';
break;
case 'F':
val = 'Female';
break;
default:
alert('error');
return 'Error!';
}
}
var dview = new google.visualization.DataView(data);
dview.setColumns([0,{calc: sexfix, type:'string'}, 2, 3]);
********/
// Define a slider control for the Age column.
var slider = new google.visualization.ControlWrapper({
'controlType': 'NumberRangeFilter',
'containerId': 'control1',
'options': {
'filterColumnLabel': 'Age',
'ui': {'labelStacking': 'vertical'}
}
});
// Define a category picker control for the Gender column
var categoryPicker = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'control2',
'options': {
'filterColumnLabel': 'Gender',
'ui': {
'labelStacking': 'vertical',
'allowTyping': false,
'allowMultiple': false
}
}
});
// Define a Pie chart
var pie = new google.visualization.ChartWrapper({
'chartType': 'PieChart',
'containerId': 'chart1',
'options': {
'width': 300,
'height': 300,
'legend': 'none',
'title': 'Donuts eaten per person',
'chartArea': {'left': 15, 'top': 15, 'right': 0, 'bottom': 0},
'pieSliceText': 'label'
},
// Instruct the piechart to use colums 0 (Name) and 3 (Donuts Eaten)
// from the 'data' DataTable.
'view': {'columns': [0, 3]}
});
// Define a table
var table = new google.visualization.ChartWrapper({
'chartType': 'Table',
'containerId': 'chart2',
'options': {
'width': '300px'
}
});
// Create a dashboard
new google.visualization.Dashboard(document.getElementById('dashboard')).
// Establish bindings, declaring the both the slider and the category
// picker will drive both charts.
bind([slider, categoryPicker], [pie, table]).
// Draw the entire dashboard.
draw(data);
}
EDIT: Solution below. In summary:
1) under dview.setColumns, include a label name as an option (e.g., "label: 'Gender'") so that controls and charts can refer to the calculated column by label;
2) draw the view, not the table (final line should be: "draw(dview)");
3) change the variable renaming in my sexfix code from general format "var = 'X'" to "return: {v: 'X' f: 'Xxxxxx'}"; and
4) either add the line "addFormattedValue: true" or use the "view:" option in the ControlWrappers and ChartWrappers to display formatted values.
I suspect that you have two problems in your code. The first is that when you added the "Gender" column to the DataView, you left off the column label, which is needed because your gender filter has the filterColumnLabel option set instead of filterColumnIndex. Add the label in to fix:
{calc: sexfix, type:'string', label: 'Gender'}
The second problem is that you are drawing your Dashboard with the DataTable instead of the DataView:
new google.visualization.Dashboard(document.getElementById('dashboard')).
// Establish bindings, declaring the both the slider and the category
// picker will drive both charts.
bind([slider, categoryPicker], [pie, table]).
// Draw the entire dashboard.
draw(dview);
I am using highstocks and I am wondering if there is anyway I can plot the y values in a column series starting from an arbitrary number. For example. I have a column series called NU (New Users) with its first entry yAxis value of 1,000. Currently, that first entry is plotted on the yAxis from range [0, 1,000]. But instead I would like it to be plotted from [5,000, 6,000].
The reason I want this is because NU is essentially apart of another column called DAU (Daily Active Users), and I want it to be shown up as so. The first entry of the DAU column series has a Y value of 6,000, and 6,000 - 1,000 is 5,000; therefore I would like this entry of NU to start at 5,000.
Here is what I have so far
http://jsfiddle.net/6JACr/2/
I was going to plot DAU as (Original DAU - NU), and stack NU on top of DAU, but that would mean the series holds an incorrect value for DAU.
Here is my code
$(document).ready(function() {
var all_series = [];
var accu_series;
var accu_data = [];
var pccu_series = [];
var pccu_data = [];
var dau_series;
var dau_data = [];
var nu_series;
var nu_data = [];
function draw_charts() {
$('#container').highcharts('StockChart', {
rangeSelector : {
selected : 1,
buttons: [{
type: 'week',
count: 1,
text: '1w'
}, {
type: 'month',
count: 1,
text: '1m'
}, {
type: 'month',
count: 3,
text: '3m'
}, {
type: 'month',
count: 6,
text: '6m'
}, {
type: 'ytd',
text: 'YTD'
}, {
type: 'year',
count: 1,
text: '1y'
}, {
type: 'all',
text: 'All'
}]
},
plotOptions: {
column: {
grouping: false
}
},
yAxis: [{
// Primary Y-Axis
labels:{
align:'right',
x:-10
},
lineWidth : 1,
offset : 0
}, {
// Secondary Y-Axis
opposite: true
}],
series : all_series
});
}
//Function that takes a record and fills the series data with that record
function fill_data(index, record) {
var date = new Date(record['dailyDate']);
var utc_date = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
accu_data[index] = [utc_date, parseFloat(record['accu'])];
dau_data[index] = [utc_date, parseFloat(record['dau'])];
nu_data[index] = [utc_date, parseFloat(record['users'])];
}
// //Function that sets up the series data for plotting
function fill_series() {
dau_series = {
name: "DAU",
type: "column",
data: dau_data,
stack: 0
};
all_series[0] = dau_series;
nu_series = {
name: "NU",
type: "column",
data: nu_data,
stack: 0
};
all_series[1] = nu_series;
}
//Pull data from API, format it, and store into the series arrays
(function() {
var result = '[{"accounts":"1668","accu":"568","activePayingRate":"1.97757","activePayingUsers":"854","activeUsers":"4905","area":"1","arpu":"34.6908","company":"45","dailyDate":"2013-08-06","dau":"6000","lost":"87","newUser":"0","paying":"96","payingRate":"1.53724","pccu":"747.0","registration":"572","sales":"3305.01","server":"1","users":"1000"},{"accounts":"1554","accu":"497","activePayingRate":"2.18398","activePayingUsers":"833","activeUsers":"4533","area":"1","arpu":"34.7479","company":"45","dailyDate":"2013-08-07","dau":"5873","lost":"89","newUser":"0","paying":"96","payingRate":"1.68568","pccu":"759.0","registration":"483","sales":"3300.04","server":"1","users":"1209"}]';
var json_result = JSON.parse(result);
$.each(json_result, function(index, record) {
fill_data(index,record);
});
fill_series();
draw_charts();
})();
});
You can use low property for column, for example: http://jsfiddle.net/6JACr/4/
To display proper tooltip, add extra property like val and use pointFormat to display it.
Note: when dataGrouping will be used custom properties are removed, in that case I advice to create your own tooltip formatter, to display what you need.