Change point colour based on value for Google Scatter Chart - google-visualization

I am creating a Google scatter chart. I have one data series which looks something like:
var data = new google.visualization.DataTable();
data.addColumn('number', 'ID');
data.addColumn('number', 'Value');
data.addRows([[1,100], [2,150],
[3,200], [4,250],
[5,300], [6,350],
[7,400], [8,450]]);
I want the colour of the points on the scatter chart to vary, between green and red, based on the 'Value' of each point.
i.e. the colour of point ID=1 should be green, however ID=8 should be red!
Is this possible?

Add an extra column to your DataTable, with the role style :
data.addColumn( {'type': 'string', 'role': 'style'} );
Now add styling to each of the rows to get the desired effect :
data.addRows([[1,100, 'point {size: 14; fill-color: green'],
[2,150, 'point {size: 14; fill-color: green'],
....
[8,450, 'point {size: 14; fill-color: red']
]);
demo -> http://jsfiddle.net/v92k8rty/
Update. There is one (out of probably hundreds) javascript library that very easily can provide a gradient palette with customizeable colors and range - RainbowVis-JS. Instead of the above, create a palette by using RainbowVis in the same range as the DataTable, and then add the colors dynamically :
//create a gradient palette from green to red using RainbowVis
var rainbow = new Rainbow();
rainbow.setNumberRange(1, data.getNumberOfRows());
rainbow.setSpectrum('green', 'red');
//alter the DataTable
data.addColumn( {'type': 'string', 'role': 'style'} );
for (var i=0;i<data.getNumberOfRows();i++) {
data.setCell(i, 2, 'point { fill-color:'+rainbow.colorAt(i+1)+'}');
}
demo -> http://jsfiddle.net/ehgfwh8z/

Related

ChartJS Tooltip - Change Data Format Displayed

I've created a horizontal floating bar chart using ChartJS. The data I am passing in is formatted as:
[
{
rowName: 'Project 1',
startDate: '2021-03-15',
endDate: '2021-04-20',
}
]
Where my x axis shows a month/year and my y axis shows the rowName. I've added chartjs-adapater-date-fns but in order to get the floating bars to work, I've had to convert the startDate and endDate into new dates and then use the .getTime() function to retrieve a number for the data the chart expects. E.g. [new Date(startDate).getTime(), new Date(endDate).getTime()].
On my tooltip, it shows the label as rowName which is what I'm wanting, however the data value shows as the two number values being passed in.
I'm wanting to show the tooltip in the following format:
Project 1
Start Date: 05/03/2021
End Date: 20/04/2021
What is the best way of doing this?
Note: I have consoled the context and found that data.raw provides me with 2021-05-03,2021-04-20 if that is of any use?
Instead of new date pass your input date , Tooltip will show with formatted date value.
var barOption = {
tooltips: {
callbacks: {
label: function(t, d) {
this.date=new Date();
let formated_date = this.datepipe.transform(this.date, 'dd/MM/yyy');
return formated_date;
},
},
},
}

Obtain max value of y axis of line chart rendered with Chart.js

I use Chart.js to render a scattered line chart, which works pretty well.
For the rendering algorithm I need to find out the highest value shown on the y-axis, so let's say my "largest" point in the dataset has y = 248, so the y-axis shows 250 as the largest value. I need to find out that it's 250.
I tried to inspect the chart object at runtime, like so:
lineChart.options.scales[0].ticks.??
but it seems that I can only find out the settings I set myself programmatically.
Also looking at the comprehensive Chart.js docs did not point me to the solution.
Any advice how to figure out this value?
There is callback method in which you can get the array of values which will show on yAxes.
The first element of that array will be the highest value for the yAxes. Below is the sample code for the same.
var yAxesticks = [];
var highestVal;
var chartInstanceHoverModeNearest = new Chart(ctx, {
type: 'bar',
data: data,
options:{
scales: {
yAxes : [{
ticks : {
beginAtZero : true,
callback : function(value,index,values){
yAxesticks = values;
return value;
}
}
}]
}
}
});
highestVal = yAxesticks[0];

Google visualization data table-getFilteredRows method

Im trying to filter column 'time' in visualization data table using getFilteredRows(filters) method.I provided column value with minimum and maximum values as,
var timesheet_dataTable = new google.visualization.DataTable(data, 0.6);
var time_filter = timesheet_dataTable.getFilteredRows([{column: 3, minValue: '2:28 PM', maxValue: '3:01 PM'}]);
and then created data view with setRows method to display the data but the table displayed without filtering the data.I checked with other column values and received proper output.So whether 'timeofday' data type is supported in this type of filters?
Is there any other method to filter column based on time?
Update:
This is the code for formatting and passing value to the visualization table.Value of variable startTime will be like '14:28:12'.
val datetimeStart: String = "Date(0,0,0,"
val datetimeEnd: String = ")"
val simpleDateTimeFormat = new SimpleDateFormat("HH,mm,ss")
Json.obj("v" -> JsString(datetimeStart + (simpleDateTimeFormat.format(tsl.startTime)).toString() + datetimeEnd))
before displaying in visualization table i have used formatter as:
var formatter_short1 = new google.visualization.DateFormat({pattern:'h:mm aa'});
formatter_short1.format(timesheet_dataTable,3);
The "timeofday" data type is supported by the filter method, you just need to use it correctly:
// filter column 3 from 2:28PM to 3:01PM
var time_filter = timesheet_dataTable.getFilteredRows([{
column: 3,
minValue: [14, 28, 0, 0],
maxValue: [15, 1, 0, 0]
}]);
var view = new google.visualization.DataView(timesheet_dataTable);
view.setRows(time_filter);
Make sure you are using the view you create to draw your chart, instead of the DataTable:
chart.draw(view, options);
[edit - example for filtering "datetime" type column]
// filter column 3 from 2:28PM to 3:01PM
var time_filter = timesheet_dataTable.getFilteredRows([{
column: 3,
minValue: new Date(0, 0, 0, 14, 28, 0, 0),
maxValue: new Date(0, 0, 0, 15, 1, 0, 0)
}]);
var view = new google.visualization.DataView(timesheet_dataTable);
view.setRows(time_filter);

Column chart: how to show all labels on horizontal axis

I've been trying to show all labels on the horizonal axis of my chart, but I haven't been able to do that!
I tried using hAxis.showTextEvery=1 but does not work
(see https://developers.google.com/chart/interactive/docs/gallery/columnchart).
Basically, I would like to also show numbers "5", "7" and "9" that are currently missing in the above chart.
Here the JavaScript code, thanks a lot.
<script type="text/javascript">
google.setOnLoadCallback(drawChart1);
function drawChart1(){
var data = new google.visualization.DataTable(
{
"cols":[
{"id":"","label":"ratings","type":"number"},
{"id":"","label":"# of movies","type":"number"}],
"rows":[
{"c":[{"v":9},{"v":26}]},
{"c":[{"v":8},{"v":64}]},
{"c":[{"v":10},{"v":5}]},
{"c":[{"v":7},{"v":50}]},
{"c":[{"v":6},{"v":38}]},
{"c":[{"v":5},{"v":10}]},
{"c":[{"v":2},{"v":1}]},
{"c":[{"v":4},{"v":1}]}
]});
var options = {
"title":"Rating distribution",
"vAxis":{"title":"# of movies","minValue":0},
"hAxis":{"title":"Ratings","maxValue":10},"legend":"none","is3D":true,"width":800,"height":400,"colors":["red"]
};
var chart = new google.visualization.ColumnChart(document.getElementById('chart_movies_per_rating'));chart.draw(data, options);
}
</script>
UPDATE:
this is the solution I developed, following the answer below (thanks again!).
http://jsfiddle.net/mdt86/x8dafm9u/104/
<script type="text/javascript">
google.setOnLoadCallback(drawChart1);
function drawChart1(){
var data = new google.visualization.DataTable(
{"cols":
[{"id":"","label":"ratings","type":"string"},
{"id":"","label":"# of movies","type":"number"}],
"rows":
[{"c":[{"v":"0"},{"v":0}]},
{"c":[{"v":" 1"},{"v":0}]},
{"c":[{"v":" 2"},{"v":1}]},
{"c":[{"v":" 3"},{"v":0}]},
{"c":[{"v":" 4"},{"v":1}]},
{"c":[{"v":" 5"},{"v":10}]},
{"c":[{"v":" 6"},{"v":38}]},
{"c":[{"v":" 7"},{"v":50}]},
{"c":[{"v":" 8"},{"v":64}]},
{"c":[{"v":" 9"},{"v":26}]},
{"c":[{"v":" 10"},{"v":5}]}
]
}
);
var options =
{"title":"Rating distribution",
"vAxis":{"title":"# of movies","minValue":0},
"hAxis":{"title":"Ratings","maxValue":10},
"legend":"none",
"is3D":true,
"width":800,
"height":400,
"colors":["CC0000"]};
var chart = new google.visualization.ColumnChart(document.getElementById('chart_movies_per_rating'));
chart.draw(data, options);
}
</script>
Your problem is related to the continuous versus discrete subtleties in ColumnChart. Basically, you have continuous values for labels on your hAxis, and the showTextEvery only works for discrete ones. To fix this, I would do the following:
Have all your missing ratings inserted into the chart (ie, if there are no values at rating '3', insert a zero).
Order the ratings in the chart. (Google charts could sort this for you, but it's likely easier to just order them.)
Change the ratings to {"id":"","label":"ratings","type":"string"},
Use the showTextEvery:1 in the options
Below is some code that demonstrates this:
var data = new google.visualization.DataTable(
{
"cols":[
{"id":"","label":"ratings","type":"string"},
{"id":"","label":"# of movies","type":"number"}],
"rows":[
{"c":[{"v":'10'},{"v":5}]},
{"c":[{"v":'9'}, {"v":26}]},
{"c":[{"v":'8'}, {"v":64}]},
{"c":[{"v":'7'}, {"v":50}]},
{"c":[{"v":'6'}, {"v":38}]},
{"c":[{"v":'5'}, {"v":10}]},
{"c":[{"v":'4'}, {"v":1}]},
{"c":[{"v":'3'}, {"v":0}]},
{"c":[{"v":'2'}, {"v":1}]},
{"c":[{"v":'1'}, {"v":0}]},
]});
var options = {
"title":"Rating distribution",
"vAxis":{"title":"# of movies","minValue":0},
"hAxis":{"title":"Ratings",showTextEvery:1},
"legend":"none",
"width":800,"height":400,"colors":["red"]
};
In addition to Jeremy's solution, another approach is to keep using continuous values on the hAxis, but specify the number of gridlines you want, which should be the same as the number of labels you want. If you want 10 labels, 1 through 10, this should work:
hAxis: { gridlines: { count: 10 } }

graphael bar chart with text x-axis

I was wondering how I can make a simple bar chart that perhaps has day as the x-axis, with values 'today' and 'yesterday', and the y-axis as perhaps 'time' with corresponding values '1' and '2'. I guess I'm confused as to how to set text as the values for the x-axis, how to show the y axis, and what exactly r.g.axis does...
(I found an example using axis = r.g.axis(0,300,400,0,500,8,2) and I only know it's the xpos, ypos,width, ??, ?? num ticks, ??). Any insight would be great! Or a page with more fully featured bar chart examples (labels, etc). Thanks.
For the sake of all those googling this:
r.g.axis(x_start, y_start, x_width, from, to, steps, orientation, labels, type, dashsize)
x_start and y_start: distance of the axis text from the bottom left corner
x_width: position of the end of the text along the x axis
from and to: used to specify and range to use instead of using the labels argument
steps: is the number of ticks - 1
orientation: seems to specify x-axis vs. y-axis
type: is the type of tick mark used.
This was all deduced from the source code. I think I'll be switching to a charting library with documentation now...
The current code (Raphaeljs 2.0) has changed and has to be slightly adapted to use Raphael.g.axis instead of r.g.axis:
Raphael.g.axis(85,230,310,null,null,4,2,["Today", "Yesterday",
"Tomorrow", "Future"], "|", 0, r)
You're on the right track. You use g.axis and the positional arguments for setting the text is found in the 'text' arg (positional) and for toggling the y using the 'orientation' args. I added an example here,
Barchart with text x-axis
Reading this Q&A and a dozen like it, I still could not get gRaphaƫl to show proper labels for a bar chart. The recipes all seemed to refer to older versions of the library, or to github pages that are no longer there. gRaphaƫl produces some great looking output--but its docs leave much to be desired.
I was, however, able to use a combination of Firebug and Inspect This Element to follow the code and see what it produced. Diving into the barchart object, the required geometry is right there. To save others the frustration, here's how I solved the problem:
<script>
function labelBarChart(r, bc, labels, attrs) {
// Label a bar chart bc that is part of a Raphael object r
// Labels is an array of strings. Attrs is a dictionary
// that provides attributes such as fill (text color)
// and font (text font, font-size, font-weight, etc) for the
// label text.
for (var i = 0; i<bc.bars.length; i++) {
var bar = bc.bars[i];
var gutter_y = bar.w * 0.4;
var label_x = bar.x
var label_y = bar.y + bar.h + gutter_y;
var label_text = labels[i];
var label_attr = { fill: "#2f69bf", font: "16px sans-serif" };
r.text(label_x, label_y, label_text).attr(label_attr);
}
}
// what follows is just setting up a bar chart and calling for labels
// to be applied
window.onload = function () {
var r = Raphael("holder"),
data3 = [25, 20, 13, 32, 15, 5, 6, 10],
txtattr = { font: "24px 'Allerta Stencil', sans-serif", fill: "rgb(105, 136, 39)"};
r.text(250, 10, "A Gratuitous Chart").attr(txtattr);
var bc = r.barchart(10, 10, 500, 400, data3, {
stacked: false,
type: "soft"});
bc.attr({fill: "#2f69bf"});
var x = 1;
labelBarChart(r, bc,
['abc','b','card','d','elph','fun','gurr','ha'],
{ fill: "#2f69bf", font: "16px sans-serif" }
);
};
</script>
<div id="holder"></div>
There are a bunch of little cleanups you could do to labelBarChart(), but this basically gets the job done.
Here's a function I wrote for adding the labels. It's not particularly elegant but it will add the labels:
Raphael.fn.labelBarChart = function(x_start, y_start, width, labels, textAttr) {
var paper = this;
// offset width and x_start for bar chart gutters
x_start += 10;
width -= 20;
var labelWidth = width / labels.length;
// offset x_start to center under each column
x_start += labelWidth / 2;
for ( var i = 0, len = labels.length; i < len; i++ ) {
paper.text( x_start + ( i * labelWidth ), y_start, labels[i] ).attr( textAttr );
}
};
Usage is as follows:
var paper = Raphael(0, 0, 600, 400);
var chart = paper.barchart(0, 0, 600, 380, [[63, 86, 26, 15, 36, 62, 18, 78]]);
var labels = ['Col 1', 'Col 2', 'Col 3', 'Col 4', 'Col 5', 'Col 6', 'Col 7', 'Col 8'];
paper.labelBarChart(0, 390, 600, labels, {'font-size': 14});
I would like to propose a solution of an issue of the labelBarChart function proposed by Jonathan Eunice.
considering stacked bar-graphes (or other bar-graphes with more than one array of values), I added a test on bc.bars[0] in case the bc.bars.length means the number of arrays of values stacked.
This lead to the code :
<script>
function labelBarChart(r, bc, labels, attrs) {
// Label a bar chart bc that is part of a Raphael object r
// Labels is an array of strings. Attrs is a dictionary
// that provides attributes such as fill (text color)
// and font (text font, font-size, font-weight, etc) for the
// label text.
//Added test : replace bc.bars by generic variable barsRef
var barsRef = (typeof bc.bars[0].length === 'undefined') ? bc.bars : bc.bars[0];
var bar, gutter_y, label_x, label_y, label_text;
//Added consideration of set attrs (if set)
var label_attr = (typeof attrs === 'undefined') ? {} : attrs;
label_attr['fill'] = (typeof label_attr['fill'] === 'undefined') ? "#2f69bf" : label_attr['fill'];
label_attr['font'] = (typeof label_attr['font'] === 'undefined') ? "16px sans-serif" : label_attr['font'];
for (var i = 0; i<barsRef.length; i++) {
bar = barsRef[i];
gutter_y = bar.w * 0.4;
label_x = bar.x
label_y = bar.y + bar.h + gutter_y;
label_text = labels[i];
r.text(label_x, label_y, label_text).attr(label_attr);
}
}
// what follows is just setting up a bar chart and calling for labels
// to be applied
// I added an array of data to illustrate : data4
window.onload = function () {
var r = Raphael("holder"),
data3 = [25, 20, 13, 32, 15, 5, 6, 10],
data4 = [0, 2, 1, 40, 1, 65, 46, 11],
txtattr = { font: "24px 'Allerta Stencil', sans-serif", fill: "rgb(105, 136, 39)"};
r.text(250, 10, "A Gratuitous Chart").attr(txtattr);
var bc = r.barchart(10, 10, 500, 400, [data3, data4] {
stacked: true,
type: "soft"});
bc.attr({fill: "#2f69bf"});
labelBarChart(r, bc,
['abc','b','card','d','elph','fun','gurr','ha'],
{ fill: "#2f69bf", font: "16px sans-serif" }
);
};
</script>
<div id="holder"></div>
I just tested it with 2 arrays of values stacked.