I tried to create line chart using google chart apis and other for following csv data. None of them helped:
csv data looks like this:
"Date,Term,Segment,Visitor"
"2014/01/01,2014/01/01 - 2014/01/31,All visitors,2"
"2014/01/01,2014/01/01 - 2014/01/31,New user,0"
"2014/01/01,2014/01/01 - 2014/01/31,Mobile traffic,0"
"2014/01/02,2014/01/01 - 2014/01/31,All visitors,7"
"2014/01/02,2014/01/01 - 2014/01/31,New user,1"
"2014/01/02,2014/01/01 - 2014/01/31,Mobile traffic,0"
"2014/01/03,2014/01/01 - 2014/01/31,All visitors,5"
"2014/01/03,2014/01/01 - 2014/01/31,New user,0"
"2014/01/03,2014/01/01 - 2014/01/31,Mobile traffic,0"
"2014/01/04,2014/01/01 - 2014/01/31,All visitors,3"
.............
I faced many issue while using google chart as you can find here:
CSV data loading give Not enough columns given to draw the requested chart
Is it possible to create line chart for this short of data?
Chart should look like this:
--------UPDATED CODE -----------
Why does it not show EVEN dates on X- axix?
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" type="text/javascript"></script>
<script src="http://jquery-csv.googlecode.com/files/jquery.csv-0.71.js"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
$.get("Chart3-data1.csv", function(csvString) {
var transData = [['Date', 'All visitors', 'New user', 'Mobile traffic']];
var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar});
for (var i = 1; i < arrayData.length; i++) {
console.log(arrayData[i][0]);
var fields = arrayData[i][0].split(',');
console.log(fields);
switch ( (i - 1) % 3) {
case 0:
var allVisitors = parseInt(fields[3]);
break;
case 1:
var newUser = parseInt(fields[3]);
break;
case 2:
var mobile = parseInt(fields[3]);
transData.push([ fields[0], allVisitors, newUser, mobile] );
break;
}
}
var data = new google.visualization.arrayToDataTable(transData);
var options =
{
title: 'Company Performance'
};
var chart = new google.visualization.LineChart(document.getElementById('gauge'));
chart.draw(data, options);
});
}
</script>
</head>
<body>
<div id="gauge" style="width: 900px; height: 500px;"></div>
</body>
</html>
Resulting graph:
I'd change your csv data to:
Date, All visitors, New user, Mobile traffic
2014/01/01, 2, 0, 0
2014/01/02, 7, 1, 0
2014/01/03, 5, 0, 0
2014/01/04, 3, 0, 2
2014/01/05, 4, 1, 2
From those data this chart is produced (no changes in code):
Change of data - one option with JS:
$.get("chart-data-orig.csv", function(csvString) {
var transData = [['Date', 'All visitors', 'New user', 'Mobile traffic']];
var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar});
// index 0 is header which will be changed
for (var i = 1; i < arrayData.length; i++) {
console.log(arrayData[i][0]);
var fields = arrayData[i][0].split(',');
console.log(fields);
switch ( (i - 1) % 3) {
case 0:
var allVisitors = parseInt(fields[3]);
break;
case 1:
var newUser = parseInt(fields[3]);
break;
case 2:
var mobile = parseInt(fields[3]);
transData.push([ fields[0], allVisitors, newUser, mobile] );
break;
}
}
var data = new google.visualization.arrayToDataTable(transData);
var options = {
title: 'Company Performance'
};
var chart = new google.visualization.LineChart(
document.getElementById('chart_div'));
chart.draw(data, options);
});
Related
I have a multi-chart Google Visualization script (1 column chart and 2 line charts). The charts are working/displaying correctly except for the var Options code. The most important part of the Options section is being able to change the column/line color. So I tried changing it using the role: 'style'} alternative, but it didn't work either.
Please see below code for the 3 charts. I'm new to Google Visualization, so any feedback/help is much appreciated!
google.charts.load('current', {
packages: ['corechart', 'controls']
}).then(function () {
// Chart data
var data = [];
data[0] = google.visualization.arrayToDataTable ([["Date","Sessions", {role: 'style'}],
<?php
for($a = 0; $a < 7; $a++)
{
echo "['".$date[$a]."', ".$sessions[$a].", 'fill-color: #76A7FA'],";
}
?>
]);
data[1] = google.visualization.arrayToDataTable ([["Date","Sessions"],
<?php
for($a = 0; $a < 31; $a++)
{
echo "['".$date[$a]."', ".$sessions[$a]."],";
}
?>
]);
data[2] = google.visualization.arrayToDataTable ([["Date","Sessions"],
<?php
for($a = 0; $a < count($query); $a++)
{
echo "['".$date[$a]."', ".$sessions[$a]."],";
}
?>
]);
var current = 0;
var current_chart = 0;
// Create and draw the visualization
var chart = [];
chart[0] = new google.visualization.ColumnChart(document.getElementById('sessions_chart'));
chart[1] = new google.visualization.LineChart(document.getElementById('sessions_chart'));
function drawChart() {
// Disabling the buttons while the chart is drawing.
document.getElementById('week_btn').disabled = true;
document.getElementById('month_btn').disabled = true;
document.getElementById('all_btn').disabled = true;
google.visualization.events.addListener(chart, 'ready', function() {
// Enable the buttons after the chart has been drawn
document.getElementById('week_btn').disabled = false;
document.getElementById('month_btn').disabled = false;
document.getElementById('all_btn').disabled = false;
});
var view = new google.visualization.DataView(data[current]);
var options = {
title: 'Number of Sessions',
vAxis: {title: "# of Sessions", minValue:0},
hAxis: {format: 'MMM d, y'},
colors: 'lightgreen'
};
// Convert first column to date format
view.setColumns([{
calc: function (dt, row) {
return new Date(dt.getValue(row, 0));
},
label: data[current].getColumnLabel(0),
type: 'date'
}, 1]);
chart[current_chart].draw(view, data[current], options);
}
drawChart();
// google.charts.setOnLoadCallback(drawChart);
document.getElementById('week_btn').addEventListener("click", displayWeek);
function displayWeek() {
current = 0;
current_chart = 0;
drawChart();
}
document.getElementById('month_btn').addEventListener("click", displayMonth);
function displayMonth() {
current = 1;
current_chart = 1;
drawChart();
}
document.getElementById('all_btn').addEventListener("click", displayAll);
function displayAll() {
current = 2;
current_chart = 1;
drawChart();
}
});
the colors option should be an array...
colors: ['lightgreen']
as for the style role, try providing only the color...
echo "['".$date[$a]."', ".$sessions[$a].", '#76A7FA'],";
AND
highly recommend NOT building json manually in php from a string.
instead, separate the php from the html in two different files.
build the data in php and return the encoded json to the page.
then use ajax to call the php page and get the encoded json.
then draw the chart.
here are some examples...
How to automatically update Google Gauge
JSON $ajax problems
The Thymeleaf block I have made in JavaScript cuts off the ending ; of the variable, and throws an Uncaught (in promise) SyntaxError: Unexpected token ' in JSON at position 2.
The code does parse like it should, except for the data variable. Parsed code:
function drawChart() {
var jsonData = "{ 'cols': [" +
"{'id':'','label':'Expense','pattern':'','type':'string'}" +
"{'id':'','label':'Amount','pattern':'','type':'number'}]," +
"'rows': [";
var data = {'Expense1': 25.0, 'Expense2': 20.0, 'Expense3': 40.0};
var end = "]}";
var res = jsonData.concat(data);
var res = res.concat(end);
var json = JSON.parse(res);
var data = new google.visualization.DataTable(json);
var options = {
title: 'Data test',
pieHole: 0.4
};
var chart = new google.visualization.PieChart(document.getElementById('donutchart'));
chart.draw(data, options);
}
Pre Thymeleaf code:
<script type="text/javascript" th:inline="javascript">
google.charts.load('current', {'packages': ['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var jsonData = "{ 'cols': [" +
"{'id':'','label':'Expense','pattern':'','type':'string'}" +
"{'id':'','label':'Amount','pattern':'','type':'number'}]," +
"'rows': [";
var data = /*[[${chart.DataPoints}]]*/;
var end = "]}";
var res = jsonData.concat(data);
var res = res.concat(end);
var json = JSON.parse(res);
var data = new google.visualization.DataTable(json);
var options = {
title: /*[[${chart.title}]]*/'',
pieHole: 0.4
};
var chart = new google.visualization.PieChart(document.getElementById('donutchart'));
chart.draw(data, options);
}
</script>
The data var is either like it is right now, or when enclosed in "", it cuts off the closing semi-colon. How do I get Thymeleaf of JavaScript to cast the data var to a string (while maintaining the '' it contains)?
Does this work for you? I don't think you need to build your data as a JSON string first, simply create it as a JavaScript object:
<script type="text/javascript" th:inline="javascript">
google.charts.load('current', {'packages': ['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var json = {
'cols': [
{'id':'', 'label': 'Expense', 'pattern': '', 'type': 'string'},
{'id':'', 'label': 'Amount', 'pattern': '', 'type': 'number'}
],
rows: []
};
var data = /*[[${chart.DataPoints}]]*/ [];
var rows = [];
Object.keys(data).forEach(function(key) {
rows.push({
"c": [
{"v": key, "f": null},
{"v": data[key], "f": null}
]
});
});
json['rows'] = rows;
var data = new google.visualization.DataTable(json);
var title = /*[[${chart.title}]]*/ '';
var options = {
title: title,
pieHole: 0.4
};
var chart = new google.visualization.PieChart(document.getElementById('donutchart'));
chart.draw(data, options);
}
</script>
edit: you can format the data however you want... it's pretty trivial to do in JavaScript.
Thank you for your answer... I'm ALMOST there :) I declared wrapper as global var, I used the getChartType method but still I'm not getting what I need.
so I have these 2 functions now:
var wrapper
function loadEditor() {
// Create the chart to edit.
var table = new google.visualization.Table(document.getElementById('table_div'));
if (sorttest == 1) {
var data = new google.visualization.DataTable(<?=$jsonTableA01?>)
} else {
var data = new google.visualization.DataTable(<?=$jsonTableB01?>)
}
wrapper = new google.visualization.ChartWrapper({
dataTable: data,
left:1,
options: {
'chartArea': {width: '60%', left: 45},
'legend' :'none',
'title':'Number of Newly Opened Roles per <?echo $_SESSION['Display']?>'
}
});
chartEditor = new google.visualization.ChartEditor();
google.visualization.events.addListener(chartEditor, 'ok', redrawChart);
chartEditor.openDialog(wrapper, {});
}
function sortABC() {
var table = new google.visualization.Table(document.getElementById('table_div'));
var CurrChartType = wrapper.getChartType();
sorttest = 1;
var data = new google.visualization.DataTable(<?=$jsonTableA01?>);
var wrapper = new google.visualization.ChartWrapper({
'chartType': CurrChartType,
dataTable: data,
left:1,
options: {
'chartArea': {width: '60%', left: 45},
'legend' :'none',
'title':'Number of Newly Opened Roles per <?echo $_SESSION['Display']?>'
}
});
I get an error on the 2nd line of sortABC()
var CurrChartType = wrapper.getChartType();
but have no idea why...
please help Bro.. :)
You could determine the chart type using google.visualization.ChartWrapper.getChartType method. In your case you could declare wrapper as global variable (it will be initialized once google.visualization.ChartWrapper is created) to make it accessible in sortABC function. Then you could get current chart type.
The following example demonstrates how to get/set chart type of Google Chart.
Complete example
google.load('visualization', '1.0', { packages: ['charteditor'] });
google.setOnLoadCallback(loadEditor);
var chartEditor = null;
var wrapper = null;
function loadEditor() {
// Create the chart to edit.
wrapper = new google.visualization.ChartWrapper({
'chartType': 'LineChart',
'dataSourceUrl': 'http://spreadsheets.google.com/tq?key=pCQbetd-CptGXxxQIG7VFIQ&pub=1',
'query': 'SELECT A,D WHERE D > 100 ORDER BY D',
'options': { 'title': 'Population Density (people/km^2)', 'legend': 'none' }
});
chartEditor = new google.visualization.ChartEditor();
google.visualization.events.addListener(chartEditor, 'ok', redrawChart);
chartEditor.openDialog(wrapper, {});
}
// On "OK" save the chart to a <div> on the page.
function redrawChart() {
chartEditor.getChartWrapper().draw(document.getElementById('vis_div'));
initChartPanel();
}
function initChartPanel() {
document.getElementById('chartpanel_div').style.visibility = 'visible';
var chartTypes = chartEditor.getChartTypes();
var select = document.getElementById('charttypes_select');
for (var i = 0; i < chartTypes.length; i++) {
var opt = document.createElement('option');
opt.innerHTML = chartTypes[i];
opt.value = chartTypes[i];
select.appendChild(opt);
}
document.getElementById('chart_info').innerHTML = wrapper.getChartType();
}
function changeChartType(sel) {
var chartType = sel.value;
wrapper.setChartType(chartType);
wrapper.draw(document.getElementById('vis_div'));
document.getElementById('chart_info').innerHTML = wrapper.getChartType();
}
#chart_info {
font-weight: bold;
}
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<div class="chart_panel" id="chartpanel_div" style=" visibility: hidden" >
<select id="charttypes_select" onchange="changeChartType(this)"></select>
Current Chart Type:<span id="chart_info"></span>
</div>
<div id="vis_div" style="height: 400px; width: 600px;"></div>
I'm trying to replicate the following code from a working example:
series: {0: {targetAxisIndex:0},
1: {targetAxisIndex:0},
2: {targetAxisIndex:1},
This is for setting which y-axis is used to plot different columns from a dataTable on a Google chart.
However I have a variable number of columns (based on user input), therefore am collecting an array of the required axis (the axisAssignment Array in the below example).
My code is below:
var series = {};
for (i=0;i<axisAssignment.length;i++)
{
series[i] = {targetAxisIndex: axisAssignment[i]};
}
return series;
However, all of my data is only being written to the left axis, despite the debugger suggesting that the object is correct. My option code is below:
var options =
{
hAxis: {title: xTitle},
vAxes: {0: {title: y1Type},
1: {title: y2Type}
},
series: calculateSeries(),
pointSize: 1,
legend: {position: 'top', textStyle: {fontSize: 10}}
};
Any assistance would be greatly apreciated.
Thanks
Tom
edit: whole file for reference (it's a work in progress so a bit of a mess I'm afraid)
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart());
function drawChart()
{
var title = "Node: "+currentNode;
var xTitle = "Date";
var yTitle = titles[currentVariable];
if (totalData !== null)
{
var tempData = newData();
var tempData2 = totalData;
dataArray[dataCount] = tempData;
var joinMark = countArray(dataCount);
totalData = google.visualization.data.join(tempData2,tempData,'full',[[0,0]],joinMark,[1]);
dataCount = dataCount+1;
}
else
{
totalData = newData();
dataArray[dataCount] = totalData;
dataCount = 1;
}
var options =
{
hAxis: {title: xTitle},
vAxes: {0: {title: y1Type},
1: {title: y2Type}
},
series: calculateSeries(),
pointSize: 0.5,
legend: {position: 'top', textStyle: {fontSize: 10}}
};
var chart = new google.visualization.ScatterChart(document.getElementById('graph'));
console.log(calculateSeries());
chart.draw(totalData, options);
function countArray(count)
{
var arrayCount= new Array();
if (count===1)
{
arrayCount[0] = count;
}
else
{
for (var i=0;i<count;i++)
{
var temp = i+1;
arrayCount[i] = temp;
}
}
return arrayCount;
}
function calculateSeries()
{
var series = {};
for (i=0;i<axisAssignment.length;i++)
{
series[i] = {targetAxisIndex: axisAssignment[i]};
}
return series;
}
function newData()
{
var dataType = dataIn[0];
dataIn.shift();
var axis = dataSelect(dataType);
axisAssignment.push(axis);
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', "Node: "+currentNode+": "+titles[currentVariable]);
var num = (dataIn.length);
data.addRows(num/2);
var i = 0;
var j = 0;
while (i<num)
{
var d = (dataIn[i]);
if (i%2===0)
{
d = new Date(d);
data.setCell(j,0,d);
i++;
}
else
{
data.setCell(j,1,parseFloat(d));
i++;
j++;
}
}
return data;
}
function dataSelect(type)
{
var axisNumber;
if (y1Type === null || y1Type === type)
{
y1Type = type;
axisNumber = 0;
}
else if (y2Type === null || y2Type === type)
{
y2Type = type;
axisNumber = 1;
}
else
{
alert("You already have 2 axes assigned.\n\nPlease clear the graph \nor select more objects of \ntype"+y1Type+" or \ntype "+y2Type+" to continue.");
axisNumber = null;
}
return axisNumber;
}
}
Ok, it seems that it's an issue with my choice of ScatterChart,
var options =
{
hAxis: {title: xTitle},
series: calculateSeries(),
vAxes: {0: {title: y1Type },
1: {title: y2Type}
},
pointSize: 0.5,
legend: {position: 'top', textStyle: {fontSize: 10}}
};
var chart = new google.visualization.LineChart(document.getElementById('graph'));
chart.draw(totalData, options);
I've changed it to LineChart and it's working fine, by keeping the pointSize option, the appearance is almost completely unchanged. Thanks for your help juvian.
I am using amCharts library on my website. On the side block I am displaying chart snapshots (thumbnails) and if clicked it goes to the chart itself. To display these snapshots they should be pre-generated but only way I can do it when I am on a chart page. Also I need to update these snapshots by schedule every day. I need a way (if possible) to generate these snapshots without visiting a webpage, ideally through command line.
At the moment I am saving charts as images on the server-side:
<script src="/static/amcharts/amcharts.js" type="text/javascript"></script>
<script src="/static/amcharts/serial.js" type="text/javascript"></script>
<script src="/static/amcharts/amstock.js" type="text/javascript"></script>
<script src="/static/amcharts/exporting/amexport.js" type="text/javascript"></script>
<script src="/static/amcharts/exporting/rgbcolor.js" type="text/javascript"></script>
<script src="/static/amcharts/exporting/canvg.js" type="text/javascript"></script>
<script src="/static/amcharts/exporting/filesaver.js" type="text/javascript"></script>
<script>
var cdata = {{ chartData|safe }};
AmCharts.ready(function () {
generateChartData();
createStockChart();
});
var chartData = [];
function generateChartData() {
for (var i = 0; i < cdata.length; i++)
{
chartData.push({
date: new Date(cdata[i]["date"]),
value: cdata[i]["value"],
volume: cdata[i]["volume"]
});
}
}
var chart;
function createStockChart() {
chart = new AmCharts.AmStockChart();
chart.exportConfig = {
menuItems: []
};
chart.addListener('rendered', function (event) {
chart.AmExport.output({format:"png", output: 'datastring'},
function(data) {
$.post("/charts/save_chart_snapshot/", {
imageData: encodeURIComponent(data)
});
});
});
chart.pathToImages = "/static/amcharts/images/";
var categoryAxesSettings = new AmCharts.CategoryAxesSettings();
categoryAxesSettings.minPeriod = "DD";
chart.categoryAxesSettings = categoryAxesSettings;
// DATASETS //////////////////////////////////////////
var dataSet = new AmCharts.DataSet();
dataSet.color = "#9cc11a";
dataSet.fieldMappings = [{
fromField: "value",
toField: "value"
}, {
fromField: "volume",
toField: "volume"
}];
dataSet.dataProvider = chartData;
dataSet.categoryField = "date";
// set data sets to the chart
chart.dataSets = [dataSet];
// PANELS ///////////////////////////////////////////
// first stock panel
var stockPanel1 = new AmCharts.StockPanel();
stockPanel1.showCategoryAxis = false;
stockPanel1.title = "Value";
stockPanel1.percentHeight = 70;
// graph of first stock panel
var graph1 = new AmCharts.StockGraph();
graph1.valueField = "value";
graph1.type = "smoothedLine";
graph1.lineThickness = 2;
graph1.bullet = "round";
graph1.bulletBorderColor = "#FFFFFF";
graph1.bulletBorderAlpha = 1;
graph1.bulletBorderThickness = 3;
stockPanel1.addStockGraph(graph1);
// create stock legend
var stockLegend1 = new AmCharts.StockLegend();
stockLegend1.valueTextRegular = " ";
stockLegend1.markerType = "none";
stockPanel1.stockLegend = stockLegend1;
// second stock panel
var stockPanel2 = new AmCharts.StockPanel();
stockPanel2.title = "Volume";
stockPanel2.percentHeight = 30;
var graph2 = new AmCharts.StockGraph();
graph2.valueField = "volume";
graph2.type = "column";
graph2.cornerRadiusTop = 2;
graph2.fillAlphas = 1;
stockPanel2.addStockGraph(graph2);
// create stock legend
var stockLegend2 = new AmCharts.StockLegend();
stockLegend2.valueTextRegular = " ";
stockLegend2.markerType = "none";
stockPanel2.stockLegend = stockLegend2;
// set panels to the chart
chart.panels = [stockPanel1, stockPanel2];
// OTHER SETTINGS ////////////////////////////////////
var scrollbarSettings = new AmCharts.ChartScrollbarSettings();
scrollbarSettings.graph = graph1;
scrollbarSettings.updateOnReleaseOnly = true;
scrollbarSettings.usePeriod = "WW"; // this will improve performance
scrollbarSettings.position = "top";
chart.chartScrollbarSettings = scrollbarSettings;
var cursorSettings = new AmCharts.ChartCursorSettings();
cursorSettings.valueBalloonsEnabled = true;
chart.chartCursorSettings = cursorSettings;
// PERIOD SELECTOR ///////////////////////////////////
var periodSelector = new AmCharts.PeriodSelector();
periodSelector.position = "top";
periodSelector.dateFormat = "YYYY-MM-DD";
periodSelector.inputFieldWidth = 150;
periodSelector.periods = [{
period: "DD",
count: 1,
label: "1 day"
}, {
period: "DD",
count: 2,
label: "2 days"
}, {
period: "DD",
count: 5,
label: "5 days"
}, {
period: "DD",
count: 12,
label: "12 days"
}, {
period: "MAX",
label: "MAX"
}];
chart.periodSelector = periodSelector;
var panelsSettings = new AmCharts.PanelsSettings();
panelsSettings.usePrefixes = true;
chart.panelsSettings = panelsSettings;
chart.write('chartdiv');
}
</script>
And this is how I save it on server-side:
def save_chart_snapshot(request):
if request.POST:
data = urllib.unquote(request.POST['imageData'])
imageData = data.split(';')[1].split(',')[1]
filename = "static/temp/charts/snapshots/" + request.POST['isin'] + ".png"
if not os.path.exists(filename):
try:
fh = open(filename, "wb")
fh.write(imageData.decode('base64'))
except IOError:
logger.error("Cannot find file or read data: " + filename)
else:
fh.close()
logger.debug("Chart snapshot is generated: " + filename)
return HttpResponse("done")
This is a bit late but I ran into a similar situation recently where I needed export report capabilities at the server-side and wanted to use amcharts.js. As I was exploring, I found that it is possible to run amcharts using puppeteer that provides a headless browser.
Below article explains it in detail:
https://www.amcharts.com/docs/v4/tutorials/automating-report-generation-using-puppeteer/
There's also a downloadable example here.
Hope this helps someone looking for similar functionality.
You can probably automate this process by visiting your charts page using a WebKit "browser" in a virtual framebuffer using a tool like uzbl-core or netserf or wkhtmltopdf or similar (all of those support JS).
Then just add the above task to a script in a cron job that's kicked-off every day.
Technically you're still visiting the page in a browser with this solution, but at least it can be reasonably automated from a headless server in a datacenter.