Can I calculate a date from the year and day number? - datetime

I have day of year data that I'm working with in a HighChart bubble chart. Data looks about like this:
[2009,265,10930],[2012,27,642],[2012,287,4929],[2010,119,1020]
The X value is the year. The Y value is the day of the year, so 119 is April 29, 265 is September 22. I'd like to actually format the Y axis as dates, but I haven't been able to find a clean way to do that. I could just reformat the data in Calc, but is there a way to calculate that in HighCharts directly?

In Highcharts it's not possible, you need to preprocess data before sending to Highcharts, just like this: http://jsfiddle.net/3bQne/1137/
Note: Highcharts requires sorted data for line/spline series.
var json = [
[2009, 265, 10930],
[2012, 27, 642],
[2012, 287, 4929],
[2010, 119, 1020]
],
DAY = 24 * 3600 * 1000,
jLen = json.length,
data = [],
i = 0;
for (; i < jLen; i++) {
var p = json[i]; // point
data.push([Date.UTC(p[0], 0, 1) + p[1] * DAY, p[2]])
}
// sort data for Highcharts
data.sort(function(a,b) { return a[0] - b[0]; } );
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container'
},
xAxis: {
type: 'datetime'
},
series: [{
data: data
}]
});

Related

Decimals in X-axis using GoogleVis line chart

I am trying to plot a simple line graph with R package GoogleVis. In my plot, my x-axis is an "year" variable. So, when I plot using year as "double", the plot shows decimals that does not exist in data, as follows:
Then I tried to use mutate and transform year to factor. So, I solved the "decimals" issue, but I got some white spaces in the graph =| , as follows:
Here is a reproducible code:
library(dplyr)
library(googleVis)
# Simple data
df <- tribble(
~year, ~value,
2014, 15,
2015, 18,
2016, 14,
2017, 25
)
# X axis with decimals
df %>% gvisLineChart() %>% plot()
# X axis with white spaces
df %>% mutate(year = as.factor(year)) %>% gvisLineChart() %>% plot()
Anyone knows how to help me? I would like to keep using the same package (googleVis), and I do not want "decimals" neither "white spaces" in x-axis.
Thanks in advance.
Wlademir.
EDITED
Code after comments:
df %>% gvisLineChart(., options = list(hAxis = "{format: '0', ticks: data.getDistinctValues(0)}")) %>% plot()
to remove the decimals, use the following configuration option when drawing the chart.
hAxis: {
format: '0'
}
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
["year", "value"],
[2014, 15],
[2015, 18],
[2016, 14],
[2017, 25],
]);
var options = {
hAxis: {
format: '0'
},
height: 288,
vAxis: {
format: '0',
viewWindow: {
min: 10,
max: 30
}
}
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
however, this can sometimes cause the labels to repeat.
although the decimal place is not shown,
the chart still uses values such as --> 2014.0, 2014.5, 2015.0, 2015.5.
this results in repeated labels --> 2014, 2014, 2015, 2015
to ensure the labels are not repeated, you can use the ticks option.
ticks is an array of values to be used on the axis.
hAxis: {
format: '0',
ticks: [2014, 2015, 2016, 2017]
}
there is also a data table method that could build this array dynamically --> getDistinctValues(columnIndex)
see following working snippet for an example...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
["year", "value"],
[2014, 15],
[2015, 18],
[2016, 14],
[2017, 25],
]);
var options = {
hAxis: {
format: '0',
ticks: data.getDistinctValues(0)
},
height: 288,
vAxis: {
format: '0',
viewWindow: {
min: 10,
max: 30
}
}
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
note: the white space is a result of converting the year numbers to strings,
as seen in the following snippet.
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
["year", "value"],
['2014', 15],
['2015', 18],
['2016', 14],
['2017', 25],
]);
var options = {
height: 288,
vAxis: {
format: '0',
viewWindow: {
min: 10,
max: 30
}
}
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
strings on the axis result in a discrete axis,
numbers a continuous axis.
the format and ticks options are not supported by discrete axis'...

How to access symbol definition attributes to perform transformation in paperjs

I am having issues rotating my symbol around a specific pivot point.
Here is my code :
var path_tank_left_track = new Path({
segments: [[0,0], [10, 0], [10,40], [0,40]], strokeColor: 'black',
closed: true
});
var path_tank_right_track = new Path({
segments: [[40,0], [50, 0], [50,40], [40,40]], strokeColor: 'black',
closed: true
});
var path_tank_body = new Path({
segments: [[10,5], [40,5], [40,35], [10,35]], strokeColor: 'black',
closed: true
});
var path_tank_gun = new Path({
segments: [[23,15], [23,0], [27, 0], [27, 15]],
strokeColor: 'black',
pivot: [25,15],
name: 'gun'
});
var path_arena_separation = new Path(new Point(view.size.width/2,0),
new Point(view.size.width/2, view.size.height));
path_arena_separation.strokeColor = 'black';
path_arena_separation.closed = true;
var whole_tank = new Group();
whole_tank.addChild(path_tank_left_track);
whole tank.addChild(new Point(5,20)); // trying to add the middle of the left track pivot point
whole_tank.addChild(path_tank_body);
whole_tank.addChild(path_tank_right_track);
whole tank.addChild(new Point(50,20)); // trying to add the middle of the right track pivot point
whole_tank.addChild(path_tank_gun);
// Create a symbol definition from the path:
var definition = new SymbolDefinition(whole_tank);
var instance1 = definition.place();
instance1.position = new Point(view.size.width/4, view.size.height/2);
var instance2 = definition.place();
instance2.position = new Point(3*view.size.width/4, view.size.height/2);
function onFrame(event) {
instance1.rotate(1, instance1.definition.item.children[1]);
}
As you can see, at the onFrame function, I'm trying to rotate the instance by 1 degree every frame around the point I created earlier. But I get an error saying the item_remove is not a function in the paper-full.js.
I'm confused, I tried to create a path with a single point and add it to the group but it did not let me.
If I modify the code to make the gun rotate on it's pivot instead, it does work :
function onFrame(event) {
instance1.definition.item.children['gun'].rotate(1, instance1.definition.item.children['gun'].pivot);
}
The gun does rotate around the proper pivot and the pivot stays attached to the symbol even if the symbol moves around. How could I achieve that behavior but turning the whole tank around a specific point relative to the center of the tank?
Thank you for your help, let me know if I should include more detail.
Your code is crashing because you try to add a point (and not a path containing a single point as you seems to be trying to) as a group child, which is not what API expects.
To create a path containing a single point, you have to do this:
var path = new Path(new Point(x,y));
But I think the idea of adding a single point path as a child to later retrieve its position to use it as a pivot point is wrong in your case.
The fact that you are creating each tank as a Symbol implies that you won't have access to its own children.
You can instead, before placing your symbols, store 2 vectors: one from center to left and one from center to right. They will later help you calculating left / right track positions.
Here is a Sketch adapted from your code, demonstrating this.
var path_tank_left_track = new Path({
segments : [ [ 0, 0 ], [ 10, 0 ], [ 10, 40 ], [ 0, 40 ] ],
strokeColor: 'black',
closed : true
});
var path_tank_right_track = new Path({
segments : [ [ 40, 0 ], [ 50, 0 ], [ 50, 40 ], [ 40, 40 ] ],
strokeColor: 'black',
closed : true
});
var path_tank_body = new Path({
segments : [ [ 10, 5 ], [ 40, 5 ], [ 40, 35 ], [ 10, 35 ] ],
strokeColor: 'black',
closed : true
});
var path_tank_gun = new Path({
segments : [ [ 23, 15 ], [ 23, 0 ], [ 27, 0 ], [ 27, 15 ] ],
strokeColor: 'black',
pivot : [ 25, 15 ],
name : 'gun'
});
var path_arena_separation = new Path(new Point(view.size.width / 2, 0), new Point(view.size.width / 2, view.size.height));
path_arena_separation.strokeColor = 'black';
path_arena_separation.closed = true;
var whole_tank = new Group();
whole_tank.addChild(path_tank_left_track);
whole_tank.addChild(path_tank_left_track);
whole_tank.addChild(path_tank_body);
whole_tank.addChild(path_tank_right_track);
whole_tank.addChild(path_tank_gun);
// store vectors from bounds center to tracks middle points
var tankCenter = whole_tank.bounds.center;
var leftTrackCenter = new Point(5, 20);
var rightTrackCenter = new Point(50, 20);
var leftVector = leftTrackCenter - tankCenter;
var rightVector = rightTrackCenter - tankCenter;
// Create a symbol definition from the path:
var definition = new SymbolDefinition(whole_tank);
var instance1 = definition.place();
instance1.position = new Point(view.size.width / 4, view.size.height / 2);
var instance2 = definition.place();
instance2.position = new Point(3 * view.size.width / 4, view.size.height / 2);
function onFrame(event)
{
// calculate pivot point position
// first we rotate vector accordingly to instance current rotation
var rotatedVector = rightVector.rotate(instance1.rotation);
// then we add it to current tank center
var point = instance1.bounds.center + rotatedVector;
// turn right
instance1.rotate(1, point);
}

Minimum tick interval (monthly) not working for datetime Highchart graph

I am working with date-time highchart and I want x-axis tick interval to appear every month(jan-12, Feb-12, Mar-12). But If the data points are less than 4 then the x-axis label starts showing days of month as well (10 dec,24 dec, 7 jan). How do I make sure that even if there are less data points or the graph is zoomed, the tick interval are monthly. Here is the code for x-axis:
xAxis : {
type: 'datetime',
tickmarkPlacement:'on',
dateTimeLabelFormats: {
month: '%b-%y',
},
minRange:1*30*24*60*60*1000,
labels : {
rotation :'280',
align:'right',
style: {
fontFamily : 'Helvetica',
fontSize: '10px'
}
}
}
Thanks in Advance
As mentioned in my earlier comment, the easiest way to get what you've asked for is to set the tickInterval:
xAxis: {
type: 'datetime',
tickInterval:86400000 * 30
}
Example:
http://jsfiddle.net/jlbriggs/Lmfa5v55/
With this setup it doesn't matter what interval your data is in - in the example, it's daily - or if it's irregularly spaced or not.
It doesn't matter what level of zoom, or how many data points, you'll have a tick and label for each month within the bounds of the data.
Try put exact interval tick, and automatic day or month will appear.
You only need format label, after put ticks.
Options.xAxis.tickPositioner = function () {
const ticks = this.series[0].xData;
let result = [];
for (let index = 0; index < ticks.length; index++) {
result.push(ticks[index]);
}
return result;
};
and format xAxis
labels: {
format: "{value:%b-%Y}",
align: "center"
}
to tooltips
tooltip: {
valueSuffix: "",
valuePrefix: "",
xDateFormat: "%B - %Y",
valueDecimals: 0
},
The problem here is that not all the months have 30 days, is better not to set the tickInterval or the minRange. You could try to generate the months at your own, like:
startDate = Date.UTC(2012, 1, 1); //your starting date
// Set the xaxis value as first day of month
for (var i = 0; i < yourData.length; i++) {
var d = new Date();
d.setTime(startDate);
d.setMonth(d.getMonth() + i);
categories.push(d.getTime());
}
Or generate your own categories as shown on Highcharts demo page:
xAxis: {
categories: [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec' //etc.
],
},
See a working demo of first option at: http://jsfiddle.net/gjkde5np/1/
Extracted from: How to set PointIntervals per month in HighChart
You could also check the code from highcharts "Time series with irregular intervals" http://www.highcharts.com/demo/spline-irregular-time . Here they use the [Date.UTC(1970, 9, 21), 0], [Date.UTC(1970, 10, 4), 0.28]

highchart change color if defiend rage is high

I have bar graph and i want to change color of graph if it goes higher than 500.
following data: days is a variable days store values from mysql how do i define low: and high: values in following code, I have tried multiple options but no luck
days variable hold values like 150, 200, 234, 655, 7434, 222
series: [{
type: 'column',
allowPointSelect: true,
data: days,
shadow : true,
showInLegend: true,
dataLabels: {
enabled: true,
},
}]
You can do this by pre-processing your data.
Something like this:
$.each(dataRaw, function(i,val) {
if(val < low) {
dataFiltered.push({"y":val,"color":"blue"});
}
else if(val > high) {
dataFiltered.push({"y":val,"color":"red"});
}
else {
dataFiltered.push(val);
}
});
You have to pre-define your high/low values, loop through your data, and build a data array that includes the color declarations for any values requiring highlight.
Example:
http://jsfiddle.net/jlbriggs/svucekrm/

Simple flot graph not updating

I'm trying to create a simple flot line graph and update it on a timer and I only want to display the last 10 points of data. But I only ever see the axis and not the graph plot. Also, I see the x axis change with the extra data but the y axis remain the same and do not correspond to the additional data. My code is as following:
var dataSet = [];
var PlotData;
var x = 0;
var y = 0;
var plot = null;
function EveryOneSec()
{
if (dataSet.length == 10)
{
dataSet.shift();
}
x++;
y += 2;
dataSet("[" + x + ", " + y + "]");
PlotData = { label: "line 1", data: [ dataSet ], color: "green" };
if (plot == null)
{
plot = $.plot($("#placeholder"), [ PlotData ], { lines: {show: true}, points: {show: true}});
}
else
{
plot.setData([ PlotData ]);
plot.setupGrid();
plot.draw();
}
setTimeout(EveryOneSec, 1000);
}
I have tried with and without the call to setupGrid() but this makes no difference to the axis display or graph plot. The x axis stop changing when I get the ticks 0 to 9 plotted even though x is incrementing past that, and the y axis remains static. I believe the code is correct above in terms of passing arrays of data, so why is the graph not appearing?
OK, you have two problems here.
First, you're not appending to your dataSet correctly. I'm not sure what the syntax you've got is doing, but what you need in each slot of the array is [x,y], which you can achieve with Array.push.
This:
dataSet("[" + x + ", " + y + "]");
Should look like this:
dataSet.push([x , y]);
And when you create your series object PlotData, you don't need to store your data inside of another array, so instead of this:
PlotData = { label: "line 1", data: [ dataSet ], color: "green" };
You need this:
PlotData = { label: "line 1", data: dataSet , color: "green" };
See it working here: http://jsfiddle.net/ryleyb/qJEXH/

Resources