Draw two google line charts from one data table - google-visualization

I collect data from my arduino sensors into a mysql table then use google graphs to draw line charts with the data. My data is temperature, humidity and a calculated humidex. Part of my project was to draw a guage with the current values which i was able to do. So I select the data into a data table, then filter them using a data view. Then draw three separate guages for each of the filtered values. The problem is temperatures usually go from -40 to 40 let's say and humidity from 0 to 100%, so drawing them in the same graph makes the graph looks flat as far as the temperatures are concerned.
My goal is to draw two graphs without having to query the database twice (if possible of course)
Below is the relevant code
echo "[new Date(" . $row["Year"] .", " .$row["Month"].", " .$row["Day"].", " .$row["Hour"].", " .$row["Min"]."), ". $temperature . ", " . $humidex . ", " . $humidity . "]";
var temp_view = new google.visualization.DataView(data);
temp_view.setRows([0,1,2]);
var humid_view = new google.visualization.DataView(data);
humid_view.setRows([0,3]);
var options = {'title':'Temperature', 'width':650, 'height':500};
var chart1 = new google.visualization.LineChart(document.getElementById('temp_chart'));
chart1.draw(temp_view, options);
var chart2 = new google.visualization.LineChart(document.getElementById('humid_chart'));
chart2.draw(humid_view, options);

if the data results in an array similar to the following...
[new Date(2018, 5, 29, 7, 26), 70, 75, 0.98]
then you only have one row with 4 columns
which means you should be using setColumns, instead of setRows...
try...
var temp_view = new google.visualization.DataView(data);
temp_view.setColumns([0,1,2]);
var humid_view = new google.visualization.DataView(data);
humid_view.setColumns([0,3]);
var options = {'title':'Temperature', 'width':650, 'height':500};
var chart1 = new google.visualization.LineChart(document.getElementById('temp_chart'));
chart1.draw(temp_view, options);
var chart2 = new google.visualization.LineChart(document.getElementById('humid_chart'));
chart2.draw(humid_view, options);

Related

ChartJS 4 migration: access other datasets from tooltip callback

I'm migrating from ChartJS 2.9.3 to 4.2.1 (current). By following the 3.x and 4.x migration guides, I've sorted most things out, but I've come across a problem that I don't see a solution for.
One of my charts is a stacked bar chart. There are two datasets for it:
let chartData = {
// other stuff...
datasets: [
{ label: "Has thing", data: [200, 250, etc] },
{ label: "Does not has thing", data: [10, 4, etc] },
]
}
In my tooltips, I was accessing both datasets to create a custom tooltip with the percent representation of each part of each stack. For instance, the tooltips for the first stack might say: "Has thing: 200 (95.2%)" and "Does not has thing: 10 (4.8%)". My callback function looked like this:
// other stuff
callbacks: {
label: function(tooltipItem, data) {
let dataset = data.datasets[tooltipItem.datasetIndex];
let count_with = data.datasets[0].data[tooltipItem.index]
let count_without = data.datasets[1].data[tooltipItem.index]
let total = count_with + count_without
let this_dataset_count = dataset.data[tooltipItem.index]
let this_dataset_perc = (this_dataset_count / total * 100).toFixed(1)
let label = dataset.label + ": "
label += this_dataset_count + " (" + this_dataset_perc + "%)"
return label;
}
}
Looking at the 3.x migration guide, it appears they removed the data parameter from the tooltip callback, opting instead to add the item's dataset directly to the tooltipItem. Unfortunately, they don't seem to specify how I can access other datasets.
Has this functionality simply been removed completely, or is there a different way to access it?
As #kikon pointed out, data is accessible via context.chart.data. For some reason, that doesn't show up for me when I console.dir() the context object so I was just completely overlooking it.
Anyway, for anyone this might help in the future, here's the working version:
callbacks: {
label: function(context) {
const datasets = context.chart.data.datasets
const countWith = datasets[0].data[context.dataIndex]
const countWithout = datasets[1].data[context.dataIndex]
const perc = (context.raw / (countWith + countWithout) * 100).toFixed(1)
return `${context.dataset.label}: ${context.formattedValue} (${perc}%)`
}
}

How to subtract the value of another row depends on Category column in PowerBI

Here is the photo explanation
I want to show the NewLinePrice in "Other Service", the value will subtract the value of "Graphic Design", so the first column will show ‭1152245‬ and so on.
So far i've tried to defined the new column "NewLinePrice", the following is the formula but not work
NewLinePrice =
Var category = 'Group-dtl'[ProductCategoryName]
var graphic_line_price = CALCULATE(SUM('Group-dtl'[LinePrice]),FILTER('Group-dtl', 'Group-dtl'[ProductCategoryName] = "Graphic Design"))
var graphic_line_price_temp = IF(category = "Graphic Design", 'Group-dtl'[LinePrice], 0)
//var graphic_line_price = 1
Var pre_result = IF(category = "Other Service", 'Group-dtl'[LinePrice] - graphic_line_price, BLANK())
Var result = IF(pre_result > 0, pre_result, BLANK())
return result
Anyone have ideas how to do that?
I spend some time to find the answer for your question, at the end I discover that to achiever your outcome, you cannot perform the calculation within the original but to create a new table, the reason is unknown, however at least it is achievable, see my answer below and accept if help, appreciate my hardworking :)
This is my original table name [Sheet1]
First I create a new table based on the original table
Table =
ADDCOLUMNS(VALUES(Sheet1[Product Name]),
"Sales",CALCULATE(SUM(Sheet1[Amount]),
FILTER(ALL(Sheet1),Sheet1[Product Name]=EARLIER(Sheet1[Product Name]))))
From the new table, I add new column using the following formula to return different value only for "Other Service"
New Line1 =
Var ServiceValue = CALCULATE(MAX(Sheet1[Amount]),Sheet1[Product Name] = "Other Service")
Var graphicValue = CALCULATE(MAX(Sheet1[Amount]),Sheet1[Product Name] = "Graphic Design")
Var charge = ServiceValue - graphicValue
return
if('Table'[Product Name] = "Other Service", charge,'Table'[Sales])
Here is new table with updated value:

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);

google visualization query limit

I have a Google visualization query for which data is coming from fusion table as,
var query = new google.visualization.Query("https://www.google.com/fusiontables/gvizdata?tq=select * from *******************");
But it select only first 500 rows of data. How to overcome this limitation?
The Fusion Tables SQL queries are deprecated. The new version of the API is not limited to 500 rows, see the Fusion Tables API for details.
Edit:
Here is an example Dashboard using the Google Fusion Tables code Odi posted in comments below:
function drawTable(response) {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Country Name');
data.addColumn('number', 'Population in 1960');
data.addColumn('number', 'Population in 2000');
var rows = [];
for (var i = 0; i < response.rows.length; i++) {
rows.push([response.rows[i][0], parseInt(response.rows[i][1]), parseInt(response.rows[i][2])]);
}
data.addRows(rows);
var table = new google.visualization.ChartWrapper({
containerId: 'table_div',
chartType: 'Table',
options: {
}
});
var control = new google.visualization.ControlWrapper({
containerId: 'control_div',
controlType: 'StringFilter',
options: {
filterColumnIndex: 0
}
});
var dashboard = new google.visualization.Dashboard(document.querySelector('#dashboard'));
dashboard.bind([control], [table]);
dashboard.draw(data);
}
function getData() {
// Builds a Fusion Tables SQL query and hands the result to dataHandler
var queryUrlHead = 'https://www.googleapis.com/fusiontables/v1/query?sql=';
var queryUrlTail = '&key=AIzaSyCAI2GoGWfLBvgygLKQp5suUk3RCG7r_ME';
var tableId = '17jbXdqXSInoNOOm4ZwMKEII0sT_9ukkqt_zuPwU';
// write your SQL as normal, then encode it
var query = "SELECT 'Country Name', '1960' as 'Population in 1960', '2000' as 'Population in 2000' FROM " + tableId + " ORDER BY 'Country Name' LIMIT 10";
var queryurl = encodeURI(queryUrlHead + query + queryUrlTail);
var jqxhr = $.get(queryurl, drawTable, "jsonp");
}
google.load('visualization', '1', {packages:['controls'], callback: getData});
See it working here: http://jsfiddle.net/asgallant/6BXsy/
Give the date format yyy-mm-dd, this is how you would create Date objects from it:
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
// other columns
var rows = [], dateArray, year, month, day;
for (var i = 0; i < response.rows.length; i++) {
dateArray = response.rows[i][0].split('-');
year = parseInt(dateArray[0]);
month = parseInt(dateArray[1]) - 1;
day = parseInt(dateArray[2]);
rows.push([new Date(year, month, day) /*, other data */]);
}
data.addRows(rows);

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 } }