I'm currently working on building a chart in highcharts, where I plot in data by week and month. This means that for every month, there will be 4.3 week-plots. My question is, is there a way to make the by-month data have a similar length as the week (aka, same starting point, and same ending point) instead of the by-month stopping abrubtly after 3-4 datapoints while the by-week stops after 15 or so?
Currently it looks like this:
This is for daily / weekly, but will be changed to weekly/monthly. Same principle applies. :)
Thanks!
So my goal here was to get the average per-week data listed along with the daily data. While I struggled for a fairly long time, the solution was rather simple.
In chart options, I needed to use datetime:
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
month: '%e. %b',
year: '%b'
}
}
After this was in place, I had to format my dates (was mysql-formatted, so YYYY-MM-DD / YYYY-WW). My biggest hurdle here was that the data was
1) Dynamic from an API endpoint
2) Differing data points (week vs days)
As I could control the API endpoint, I could perform the changes to the dates there to avoid the performance loss on client side. The data needs to be in timestamp w/ ms, and to do this I used momentjs. Example below is for weeks:
let d = moment(i.date, 'YYYY-WW').format('YYYY-MM-DD')
let dateFormat = new Date(d);
let date = moment(d).day(parseInt(goToDay)).format('YYYY-MM-DD').split('-')
let utcDate = Date.UTC(parseInt(date[0]), parseInt(date[1]) - 1, parseInt(date[2]))
Days were easier:
let date = i.date.split('-');
let utcDate = Date.UTC(date[0], date[1] - 1, date[2])
After this, it was only a matter of sending the data back to the client, and looping over it like so (note I'm using angular, procedure for highcharts w/o angular would be slightly different):
$scope.ChartConfig.series = [];
$scope.ChartConfig.series.push({
name: 'Daily',
title: 'Daily',
data: data.daily.data
})
$scope.ChartConfig.series.push({
name: 'Weekly',
title: 'Weekly',
data: data.weekly.data
});
This renders the charts perfectly, and just the way I want it to:
Related
Current implementation:
Desired implementation:
If you look carefully there is a vertical line connecting threshold with the first point of my displayed chart. Any ideas how to implement it ? What I thought was to get the threshold price (got it)and find a way to insert it a starting point, but I struggle a bit (since i use unix timestamp).Thanks in advance !
I parse the data from Monday to Friday, but I only display Intraday's data (let's say I am o Friday now). So the threshold will be the closing price from Thursday.
You are right. Inserting a starting point seems to be the best solution for that. You can do it as below:
const threshold = 10;
const data = [
[20, 11],
...
];
data.unshift([data[0][0], threshold]);
Highcharts.chart('container', {
series: [{
type: 'area',
threshold,
data
}]
});
Live demo: http://jsfiddle.net/BlackLabel/7ynzhmuv/
API Reference: https://api.highcharts.com/highcharts/series.area.threshold
I'm using Searchkick in a Rails project with an ElasticSearch 6.8 server. I'm trying to boost certain documents that have a year field that's equal to this year or a year in the future.
I've tried using boost_where and most recently boost_by but neither work. boost_by generates a function_score function that errors out in ElasticSearch. Here's my most recent try.
Model.search('value', boost_by: { year: { scale: '5y' } })
ElasticSearch seems to dislike the calendar interval (5y) even though this should be valid. Here's the reason object from the error:
"caused_by": {
"type": "number_format_exception",
"reason": "For input string: \"5y\""
}
I've tried setting origin and decay along with scale but that doesn't seem to help anything.
Here is the query generated by Searchkick (model and field names changed due to a very specific domain model).
Model Search (163.5ms) model_development/_search {"query":{"function_score":{"functions":[{"weight":1,"gauss":{"year":{"scale":"5y"}}}],"query":{"bool":{"should":[{"dis_max":{"queries":[{"multi_match":{"query":"Abreu","boost":10,"operator":"and","analyzer":"searchkick_search","fields":["*.analyzed"],"type":"best_fields"}},{"multi_match":{"query":"Abreu","boost":10,"operator":"and","analyzer":"searchkick_search2","fields":["*.analyzed"],"type":"best_fields"}},{"multi_match":{"query":"Abreu","boost":1,"operator":"and","analyzer":"searchkick_search","fuzziness":1,"prefix_length":0,"max_expansions":3,"fuzzy_transpositions":true,"fields":["*.analyzed"],"type":"best_fields"}},{"multi_match":{"query":"Abreu","boost":1,"operator":"and","analyzer":"searchkick_search2","fuzziness":1,"prefix_length":0,"max_expansions":3,"fuzzy_transpositions":true,"fields":["*.analyzed"],"type":"best_fields"}}]}}]}},"score_mode":"sum"}},"timeout":"11s","_source":false,"size":10000}
Year is likely not a supported date format due to it not having an absolute representation. One day is always 24 hours, but one year is sometimes 364 days and usually 365 days. Rather than solve for this complexity, ES likely stops at days.
If you want, you can instead use days for your scale:
Model.search('value', boost_by: { year: { scale: '1825d' } })
I have a chart which displays goals between 1995 and 2030. I need the series to "stop" at the current year.
The x-axis:
xAxis: {
categories: ['1995', '1996', '1997', '1998', '1999', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '2010', '2011', '2012', '2015', '2016', '2017','2018', '2019', '2020', '2021', '2022', '2023', '2024', '2025', '2026', '2027' , '2028', '2029', '2030'],
tickmarkPlacement: 'on',
title: {
enabled: false
}
},
The series:
series: [{
name: 'Consumption',
data: [5020, 4350, 3090, 2500, 2100, 800]
}],
If I do like this, the categories is automatically matched to the number of series data.
Is there any option where I can keep all the categories?
http://jsfiddle.net/zh4yukL8/1/
There are multiple ways to do this, but answer (2) may be the most useful in your case.
1) Using nulls for unknown data
If you have missing data for certain years (and you want to stop the graph intermittently), you can write unknown data as a 'null' in the series data (as #wergeld mentions in his comment above).
This is useful if you are programmatically filling in data for your graph and your program is working through each category in turn. If you only have data up until the year 2000, your program should work up to your end year (or any other end category), placing nulls in the series where there is no data available.
2) Using pointStart & max with a datetime chart
Seeing as you're dealing with years, you can make this chart more effective at displaying your series. You can select the start year (pointStart) and end year (max); with your data starting from the start year, and the series continuing until the end year.
Your xAxis will change to:
xAxis: {
type: 'datetime',
max: Date.UTC(2030, 0, 1)
}
And you'll need some plotOptions*:
plotOptions: {
series: {
pointStart: Date.UTC(1995, 0, 1),
pointIntervalUnit: 'year'
}
}
Example here: http://jsfiddle.net/zh4yukL8/5/ .
If you have missing data for some years, you can fill these with nulls in the series data as method (1) explains, but the graph will continue until the max year anyway.
*While playing around with this example, I discovered that the AngularJS Highcharts library (highcharts-ng) you're using expects plotOptions to be dealt with differently to native Highcharts JS. So the example above works with your library, but for everyone else you will need to have plotOptions outside of the 'options' object.
3) Using a function to work out the length of your series
If your chart doesn't just deal with years and/or you want a discrete series represented, you can use the max property on the xAxis and a clever function to work out how many categories you have. The best way I can see to include this function in Highcharts seems to be on the load event of the chart.
You'll need to adapt your chart* options to include the event:
chart: {
events: {
load: function () {
var totalValues = this.xAxis[0].categories.length;
this.xAxis[0].setExtremes(0 , totalValues - 1 );
}
}
}
Example here: http://jsfiddle.net/zh4yukL8/6/
*As with method (2), the 'chart' options when using the highcharts-ng library for AngularJS are inside the 'options' object.
I have this fiddle which enables you to get the selected period of time using the afterSetExtremes() event.
My problem is figuring out how to get a sum of the y-axis data for selected period.
I see that in the event object via target > series > data you can get the currently selected points and then loop through them getting a sum of the total, however it seems a bit of an unwieldy method and I was wondering if there was a quick simple API function which would give you this data a little more cleanly?
Edit - found an example of how to do this by the original author so presume there is no other way.
Thanks,
http://jsfiddle.net/L3rych99/1/
xAxis:{
events: {
afterSetExtremes:function(event){
var start_date = new Date(event.min);
var end_date = new Date(event.max);
//console.log(event)
//console.log(start_date + ' ' + end_date);
//how to get sum of y-axis data between start and end data?
},
},
},
Im trying to mark certain Day Times on my Chart - iE: 15:00 - 21:00
The Date information comes in form of a timestamp - "1365362890000" for example.
Is there any convenient way to say start from time X and go until time Y?
Else I would probs need to loop through all the times to find start/end points.
The timeframe can be anything from a day to a month.
(The plotBands themselves are working for me - just looking if there might be a better way then looping through all the data)
Edit: I meant something like you see in my picture here - its working like this and all is fine. Im just wondering if there was a simple way to say - "mark time x to time y with color z" instead of doing "by hand".
Yes, plotBands have a #from and #to property. Just use the #from and #to of the converted datetime (i.e. the unix time * 1000)
$('#container').highcharts('StockChart', {
xAxis: {
plotBands: [
{
from: 1374658200000,
to: 1374681600000,
color: "rgba(68, 170, 213, .2)"
}
]
}
});
In the xAxis you can set min value and tickInterval.
http://api.highcharts.com/highcharts#xAxis.tickInterval
http://api.highcharts.com/highcharts#xAxis.min (should be timestamp too)
Also you can define pointStart for serie: http://api.highcharts.com/highcharts#plotOptions.series.pointStart and pointInterval http://api.highcharts.com/highcharts#plotOptions.series.pointInterval