I am using the Google Column Chart to visualize data.
Problem:
Unfortunately with a certain input the heights of the column bars are not in proportion.
Error Reproduction:
I reconstructed this in a simple JsFiddle.
Here is an other example, which contains a working and a not working version.
Question:
How can the issue be fixed, so that the height is proportional to the value differences of my columns.
If for example one column has the value 20.000 and an other 40.000, the height of the first one should be half as high as for the second column.
Thank you so much.
Code examples & images:
Here is my jsFiddleCode:
Html:
<body>
<h1>
Weird height of Google Column Chart Bars.
</h1>
<div id="columnchart_values"></div>
<h1>
Correct height of Google Column Chart Bars.
</h1>
<div id="columnchart_values2"></div>
</body>
Javascript:
function numberWithCommas(x) {
var parts = x.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ".");
if( typeof( parts[1] ) != 'undefined' ){
parts[1] = parts[1].substr(0,2);
}
return parts.join(",");
}
function drawChart1() {
var data = google.visualization.arrayToDataTable([
['Quelle', 'Geldbetrag', { role: 'style' }, { role: 'annotation' } ],
['test1', 40000, '#11368A', 'Cu' ],
['test2', 29400, '#000357', 'Ag' ],
['test3', 22193, '#40F020', 'Au' ],
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1,
{ calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation" },
2]);
var options = {
title: "Density of Precious Metals, in g/cm^3",
width: 600,
height: 400,
bar: {groupWidth: "95%"},
legend: { position: "none" },
};
var chart = new google.visualization.ColumnChart(document.getElementById("columnchart_values"));
chart.draw(view, options);
}
function drawChart2() {
/*only the data of test 3 changed*/
var data = google.visualization.arrayToDataTable([
['Quelle', 'Geldbetrag', { role: 'style' }, { role: 'annotation' } ],
['test1', 40000, '#11368A', 'Cu' ],
['test2', 29400, '#000357', 'Ag' ],
['test3', 19000, '#40F020', 'Au' ],
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1,
{ calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation" },
2]);
var options = {
title: "Density of Precious Metals, in g/cm^3",
width: 600,
height: 400,
bar: {groupWidth: "95%"},
legend: { position: "none" },
};
var chart = new google.visualization.ColumnChart(document.getElementById("columnchart_values2"));
chart.draw(view, options);
}
google.charts.load('current', {packages: ['corechart'], 'language': 'de'});
google.charts.setOnLoadCallback( function(){
drawChart1();
drawChart2();
} );
The current behavior is to remain backward compatible with the way it used to be years ago. Now it will include the baseline value in the chart if it is "close enough" to the data. But you can force the baseline value of the bars to be included in the chart by simply specifying the baseline value explicitly. For your example, just add:
vAxis: { baseline: 0 }
to your options. See https://jsfiddle.net/2betxw5u/2/
Adding: vAxis: {minValue: 0, format: '€ #,###'} to the options solves the problem.
My JSON array, which I'm getting by ajax response, looks like that:
[["\u041f\u0435\u0440\u0438\u043e\u0434","\u041a\u043b\u0438\u0435\u043d\u0442\u044b","\u0421\u0434\u0435\u043b\u043a\u0438","\u0421\u0443\u043c\u043c\u0430 \u0441\u0434\u0435\u043b\u043e\u043a","\u041e\u043f\u043b\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u0441\u0434\u0435\u043b\u043a\u0438"],["2017-02-18",0,0,0,0],["2017-02-19",1,0,0,0],["2017-02-20",2,0,0,0],["2017-02-21",4,1,64000,0],["2017-02-22",0,0,0,0],["2017-02-23",3,0,0,0],["2017-02-24",1,0,0,0],["2017-02-25",0,0,0,0],["2017-02-26",2,0,0,0],["2017-02-27",1,1,50000,0],["2017-02-28",1,0,0,0]...etc
So, everythings works fine, my X-axis labels looks good, but I can't understand how can I:
1) make them in date format for Google Chart understand that this is date and
2) group them by month by clicking some button
All problems come from my way of Google Charts implementing.
Here's the code.
function drawChart() {
var obj ='[["\u041f\u0435\u0440\u0438\u043e\u0434","\u041a\u043b\u0438\u0435\u043d\u0442\u044b","\u0421\u0434\u0435\u043b\u043a\u0438","\u0421\u0443\u043c\u043c\u0430 \u0441\u0434\u0435\u043b\u043e\u043a","\u041e\u043f\u043b\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u0441\u0434\u0435\u043b\u043a\u0438"],["2017-02-18",0,0,0,0],["2017-02-19",1,0,0,0],["2017-02-20",2,0,0,0],["2017-02-21",4,1,64000,0],["2017-02-22",0,0,0,0],["2017-02-23",3,0,0,0],["2017-02-24",1,0,0,0],["2017-02-25",0,0,0,0],["2017-02-26",2,0,0,0],["2017-02-27",1,1,50000,0],["2017-02-28",1,0,0,0],["2017-03-01",0,0,0,0],["2017-03-02",6,0,0,0],["2017-03-03",2,0,0,0],["2017-03-04",1,0,0,0],["2017-03-05",1,0,0,0],["2017-03-06",10,0,0,0],["2017-03-07",1,0,0,0],["2017-03-08",1,0,0,0],["2017-03-09",0,0,0,0],["2017-03-10",9,0,0,0],["2017-03-11",0,0,0,0],["2017-03-12",3,0,0,0],["2017-03-13",3,0,0,0],["2017-03-14",1,0,0,0],["2017-03-15",6,0,0,0],["2017-03-16",1,0,0,0],["2017-03-17",1,0,0,0],["2017-03-18",0,0,0,0],["2017-03-19",5,0,0,0],["2017-03-20",5,0,0,0]]';
data = google.visualization.arrayToDataTable($.parseJSON(obj));
var options = {
crosshair: {
trigger: 'both',
orientation: 'vertical'
},
focusTarget: 'category',
chartArea:{left:40,top:40,width:"85%"},
hAxis: {
format: 'MM'
},
vAxes: {
0: {},
1: {title: 'Cумма'},
},
series: {0: {targetAxisIndex:0},
1:{targetAxisIndex:0},
2:{targetAxisIndex:1},
3:{targetAxisIndex:1},
},
animation:{
duration: 750,
// easing: 'out',
startup: true
},
backgroundColor: 'aliceblue'
};
var chart = new google.visualization.LineChart(
document.getElementById('chart_div')
);
chart.draw(data, options);
}
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://www.google.com/jsapi?ext.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div" style="width: 100%; height: 400px;"></div>
1) for google to recognize the first column as a date, need to use the following format in the json...
"Date(year, month, day, hours, minutes, days, seconds, milliseconds)"
e.g.
["Date(2017, 1, 18)",0,0,0,0],["Date(2017, 1, 19)",1,0,0,0],
month is zero-based --> 1 = Feb
or, you can use a view and a calculated column to convert, see snippet...
2) use the group() method to group by month
see following working snippet...
function drawChart() {
var obj ='[["\u041f\u0435\u0440\u0438\u043e\u0434","\u041a\u043b\u0438\u0435\u043d\u0442\u044b","\u0421\u0434\u0435\u043b\u043a\u0438","\u0421\u0443\u043c\u043c\u0430 \u0441\u0434\u0435\u043b\u043e\u043a","\u041e\u043f\u043b\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u0441\u0434\u0435\u043b\u043a\u0438"],["2017-02-18",0,0,0,0],["2017-02-19",1,0,0,0],["2017-02-20",2,0,0,0],["2017-02-21",4,1,64000,0],["2017-02-22",0,0,0,0],["2017-02-23",3,0,0,0],["2017-02-24",1,0,0,0],["2017-02-25",0,0,0,0],["2017-02-26",2,0,0,0],["2017-02-27",1,1,50000,0],["2017-02-28",1,0,0,0],["2017-03-01",0,0,0,0],["2017-03-02",6,0,0,0],["2017-03-03",2,0,0,0],["2017-03-04",1,0,0,0],["2017-03-05",1,0,0,0],["2017-03-06",10,0,0,0],["2017-03-07",1,0,0,0],["2017-03-08",1,0,0,0],["2017-03-09",0,0,0,0],["2017-03-10",9,0,0,0],["2017-03-11",0,0,0,0],["2017-03-12",3,0,0,0],["2017-03-13",3,0,0,0],["2017-03-14",1,0,0,0],["2017-03-15",6,0,0,0],["2017-03-16",1,0,0,0],["2017-03-17",1,0,0,0],["2017-03-18",0,0,0,0],["2017-03-19",5,0,0,0],["2017-03-20",5,0,0,0]]';
var data = google.visualization.arrayToDataTable($.parseJSON(obj));
// create date formatter
var formatDate = new google.visualization.DateFormat({
pattern: 'MM'
});
// create view with calculated column
var view = new google.visualization.DataView(data);
view.setColumns([
// col 0 - x
{
label: 'date',
type: 'date',
calc: function (dt, row) {
return new Date(dt.getValue(row, 0))
}
},
// col 1 - y
1
]);
// group by month
var groupData = google.visualization.data.group(
// data table
view,
// group by fields
[{column: 0, type: 'string', modifier: function (xValue) {
return formatDate.formatValue(new Date(xValue));
}}],
// aggregate fields
[
{
aggregation: google.visualization.data.sum,
column: 1,
label: 'Total',
type: 'number'
}
]
);
var options = {
crosshair: {
trigger: 'both',
orientation: 'vertical'
},
focusTarget: 'category',
chartArea:{left:40,top:40,width:"85%"},
hAxis: {
format: 'MM'
},
vAxes: {
0: {},
1: {title: 'C????'},
},
series: {0: {targetAxisIndex:0},
1:{targetAxisIndex:0},
2:{targetAxisIndex:1},
3:{targetAxisIndex:1},
},
animation:{
duration: 750,
easing: 'inAndOut',
startup: true
},
backgroundColor: 'aliceblue'
};
var chart = new google.visualization.LineChart(
document.getElementById('chart_div')
);
// draw grouped data
chart.draw(groupData, options);
}
google.charts.load('current', {
callback: function () {
drawChart();
window.addEventListener('resize', drawChart, false);
},
packages:['corechart']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div id="chart_div"></div>
I have a Google combo chart that has one value as bars and one value for a line, I also wanted a line to show the average of the value of the bars, so I found code that would do that, however, when implemented my other line disappeared.
This is what my chart looked like prior.
And this is after I implemented the average line, my other line disappeared.
I don't know how to do to make them both show?
This line seems to have things to do with all of it, changing dv back to data will show how my chart looked like on the first picture, but I guess there is something more I need to change to make it all work?
chart.draw(dv, options);
Here is the code.
<script>
google.charts.load('current', {
'packages': ['corechart']
});
google.charts.setOnLoadCallback(drawVisualization);
function drawVisualization() {
var data = google.visualization.arrayToDataTable([
['Day', 'Repetitions', 'Sets'],
#foreach (var c in db.Query(Query, inputDate, endDate, baselift))
{
var totAvg = c.avg;
var allReps = c.reps;
var realAvg = (totAvg / allReps) * 100;
//Writes out the data that will be shown in the chart.
<text>['#c.date', #c.reps, #c.sets],</text>
}
]);
// Create a DataView that adds another column which is all the same (empty-string) to be able to aggregate on.
var viewWithKey = new google.visualization.DataView(data);
viewWithKey.setColumns([0, 1, {
type: 'string',
label: '',
calc: function (d, r) {
return ''
}
}])
// Aggregate the previous view to calculate the average. This table should be a single table that looks like:
// [['', AVERAGE]], so you can get the Average with .getValue(0,1)
var group = google.visualization.data.group(viewWithKey, [2], [{
column: 1,
id: 'avg',
label: 'Average',
aggregation: google.visualization.data.avg,
'type': 'number'
}]);
// Create a DataView where the third column is the average.
var dv = new google.visualization.DataView(data);
dv.setColumns([0, 1, {
type: 'number',
label: 'Average',
calc: function (dt, row) {
return group.getValue(0, 1);
}
}]);
var options = {
title: 'Daily Repetition Statistics',
backgroundColor: { fill: 'transparent' },
explorer: { axis: 'horizontal' },
vAxes: {
0: { logScale: false, viewWindow: { min: 0 } },
1: { logScale: false, maxValue: 2 }
},
hAxis: { title: 'Day' },
seriesType: 'bars',
curveType: 'function',
series: {
0: {
targetAxisIndex: 0,
color: 'orange'
},
1: { targetAxisIndex: 1 },
1: { targetAxisIndex: 1, type: "line" },
2: { targetAxisIndex: 1, type: "line" }
}
};
var chart = new google.visualization.ComboChart(document.getElementById('chart_div'));
chart.draw(dv, options);
}
</script>
the column index for 'sets' is not provided to setColumns
change this...
var dv = new google.visualization.DataView(data);
dv.setColumns([0, 1, {
type: 'number',
label: 'Average',
calc: function (dt, row) {
return group.getValue(0, 1);
}
}]);
to..
var dv = new google.visualization.DataView(data);
dv.setColumns([0, 1, 2, { // <-- add 'sets' column index 2
type: 'number',
label: 'Average',
calc: function (dt, row) {
return group.getValue(0, 1);
}
}]);
I wanted to make a google chart which shows the dual y axis , but both should represents the same bar.
See this fiddle
google.charts.load('current', {'packages':['bar']});
google.charts.setOnLoadCallback(drawStuff);
function drawStuff() {
var data = new google.visualization.arrayToDataTable([
['Car', 'Distance travelled'],
["mercedes", 44],
["lamborgh", 31],
["porsche", 12],
["aston martin", 10]
]);
var options = {
title: 'Car distance',
width: 500,
legend: { position: 'none' },
chart: { subtitle: 'money spent in distance travelled' },
axes: {
x: {
0: { side: 'top', label: 'Car stats'} // Top x-axis.
}
},
bar: { groupWidth: "20%" }
};
var chart = new google.charts.Bar(document.getElementById('top_x_div'));
// Convert the Classic options to Material options.
chart.draw(data, google.charts.Bar.convertOptions(options));
};
I have shown the Cars distance traveled , thats actually in kms, now i wanted to show the cars money spent in fuel
like a car traveled 1km and it spends $2 in fuel
now looking at the fiddle suppose we have mercedes car traveled 44km then it costs around $88 which should be depicted by the 2nd y-axis
How it can be done?
each series (y-value) in the chart represents a column in the data
"series 0" = column 1 in the data
"series 1" = column 2 in the data
then use the options to map each series to an axis...
series: {
0: { axis: 'distance' },
1: { axis: 'fuel' }
},
axes: {
y: {
distance: {label: 'Distance'},
fuel: {side: 'right', label: 'Fuel'}
}
}
see following working snippet...
google.charts.load('current', {
callback: drawChart,
packages:['bar']
});
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Car', 'Distance travelled', 'Fuel'],
['mercedes', 44, 88],
['lamborgh', 31, 62],
['porsche', 12, 24],
['aston martin', 10, 20]
]);
var options = {
title: 'Car distance',
height: 500,
legend: { position: 'none' },
chart: { subtitle: 'money spent in distance travelled' },
bar: { groupWidth: "20%" },
series: {
0: { axis: 'distance' },
1: { axis: 'fuel' }
},
axes: {
x: {
0: { side: 'top', label: 'Car stats'} // Top x-axis.
},
y: {
distance: {label: 'Distance'},
fuel: {side: 'right', label: 'Fuel'}
}
}
};
var chart = new google.charts.Bar(document.getElementById('chart_div'));
chart.draw(data, options);
};
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
EDIT
to remove the second bar but keep the axis requires a bit of manipulation
and use of options not available to material charts
see following working snippet using a core chart...
google.charts.load('current', {
callback: drawChart,
packages:['bar', 'corechart']
});
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Car', 'Distance travelled'],
['mercedes', 44],
['lamborgh', 31],
['porsche', 12],
['aston martin', 10]
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
label: 'Fuel',
type: 'number',
calc: function () {
return null;
}
}]);
var options = {
title: 'Car distance',
height: 500,
legend: { position: 'none' },
chart: { subtitle: 'money spent in distance travelled' },
bar: { groupWidth: "20%" },
// center bar with x-axis label
isStacked: true,
// material chart theme
theme: 'material',
// y-axis settings
vAxes: {
0: {
ticks: [0, 10, 20, 30, 40, 50],
title: 'Distance'
},
1: {
ticks: [0, 20, 40, 60, 80, 100],
title: 'Fuel'
}
},
// map series
series: {
0: {
targetAxisIndex: 0
},
1: {
targetAxisIndex: 1
}
}
};
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
chart.draw(view, options);
};
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
note
material charts --> packages:['bar'] -- google.charts.Bar
core charts --> packages:['corechart'] -- google.visualization.ColumnChart