I will need to display objects (a doublebar chart for each object). The structure of the object is:
{
dates: (5) ["2018-12-26", "2018-12-27", "2018-12-28", "2018-12-31", "2019-01-02"]
formattedDates: (5) ["2018/12/26", "2018/12/27", "2018/12/28", "2018/12/31", "2019/01/02"]
formatPoints2: (5) [1545945000000, 1546026562061, 1546284847056, 1546465543023, 1546545993086]
points: (5) ["2018-12-27T10:36:24.893", "2018-12-28T17:29:56.517", "2018-12-31T05:48:41.587", "2019-01-01T10:10:09.683", "2019-01-03T10:36:42.002"]
points2: (5) ["2018-12-27T16:10", "2018-12-28T14:49:22.061", "2018-12-31T14:34:07.056", "2019-01-02T16:45:43.023", "2019-01-03T15:06:33.086"]
formatPoints: (5) [1545924984893, 1546036196517, 1546253321587, 1546355409683, 1546529802002]
}
I took the liberty of converting the points and points 2 array using date.getTime() to get the formatPoints and formatPoints2
what I need to do is plot the time of the timestamps vs the dates.
e.g. points[0] = 2018-12-27T10:36:24.893, dates[0] = 2018-12-26
plot 10:36:24 vs 2018-12-26 and so on for each time in the array
an extra catch I need to display the FULL timestamp in the tool-tip (2018-12-27T10:36:24.893) on the chart when you hover over the bar for that point
the chart is a double bar chart where points&points2 is plotted against dates.
In your case the key is to set the right axis types. For timestamp values on yAxis the best type will be datetime and for dates on xAxis - category. Please check the example below and let me know if everything is fine.
var series = [{data: []}, {data: []}];
data.points.forEach(function(point, i){
series[0].data.push({
name: data.formattedDates[i],
tooltipText: data.points[i],
y: data.formatPoints[i]
});
series[1].data.push({
name: data.formattedDates[i],
tooltipText: data.points2[i],
y: data.formatPoints2[i]
});
});
Highcharts.chart('container', {
chart: {
type: 'bar'
},
xAxis: {
type: 'category'
},
tooltip: {
pointFormat: '{point.tooltipText}'
},
yAxis: {
min: 1545945000000,
max: 1546529802002,
type: 'datetime'
},
series: series
});
Live demo: http://jsfiddle.net/BlackLabel/asm64f5r/
API: https://api.highcharts.com/highcharts/xAxis.type
Related
I am trying to create a grouped bar chart using Observable's Plot.plot in JavaScript (code is in TypeScript).
The problem is that the x-axis is showing each specific date, however I want the dates to show dynamic months or weeks, not specific dates.
This is the code:
const chart = Plot.plot({
x: { axis: null, domain: ["Add", "Remove"], },
y: { tickFormat: "s", label: "↑ Access Requests", grid: true },
color: {
legend: true,
type: "categorical",
domain: ["Add", "Remove"],
range: redGreenColorRange,
},
style: {
background: "transparent",
},
width: 1350,
caption: "in 2 week increments",
facet: {
data: groupedAddRemove,
label: "Created Date",
x: "createdDate",
// thresholds: d3.utcWeeks,
// ^ this doesn't work, but a similar structure has worked in other projects I've seen
},
marks: [
Plot.barY(groupedAddRemove, {
x: "type",
y: "count",
fill: "type",
}),
Plot.ruleY([0]),
],
});
and this is what it looks like:
I want the x-axis marks to show a dynamic version of Months, like:
My data structure either could show the "Date" as a string, or a TypeScript typeof Date object
data structure with date with a type of string
data structure with date with a type of Date
This is the data structure type:
The 'groupedAddRemove' is an array of this type
( AddRemoveBarChartType[] )
type AddRemoveBarChartType = {
createdDate: Date;
count: number;
type: "Add" | "Remove";
};
the "Type" can either be "Add" or "Remove". I had a boolean for this value previously, but the "Add" and "Remove" fit better to automatically have the legend say "Add" and "Remove". It could be changed back to a boolean if there is a better way to display it that way.
The data could be changed in other ways too, if that will simplify things. I am also open to using a D3.js implementation instead of Plot.plot.
I'm very new to Observable Plot.plot so any help is appreciated, thank you!
I am using Echarts, and I want to color my series (the trends, not the background) with different ranges. The following example is almost what I need:
But with two modifications:
I have a "time" axis instead of a "category" axis.
For the ranges of the series that are not specified in the visualMap, I want them to keep their original, random-generated color.
I just modified the code in the previous example to try to do it, with no luck:
var values = [];
for(var i = 0; i < 15; i++) {
var date = new Date();
date.setDate(date.getDate() + i);
values.push([date, i])
}
const firstDate = values[1][0];
const lastDate = values[5][0];
option = {
xAxis: {
type: 'time',
boundaryGap: false,
},
yAxis: {
type: 'value',
},
visualMap: {
pieces: [{
gt: firstDate,
lte: lastDate,
color: 'green'
}]
},
series: [
{
type: 'line',
data: values,
}
]
};
I just get errors like:
Uncaught DOMException: Failed to execute 'addColorStop' on 'CanvasGradient': The value provided ('undefined') could not be parsed as a color.
t.indexOf is not a function at py (echarts.min.js:formatted:15975)
I do not see any information related with time axes in the visualMap documentation.... any ideas?
I know you can pass arbitrary data into your time series points, such as:
new Highcharts.Chart( {
...,
series: [{
name: 'Foo',
data: [ { y : 10.0, customData : 'value 1' },
{ y : 20.0, customData : 'value 2' },
{ y : 30.0, customData : 'value 3' } ]
}]
} );
However, I noticed that this doesn't quite work in HighStock when your time series is comprised of a large data set (1000+ points).
For example, here is a working fiddle http://jsfiddle.net/gparajon/c5fej775/ (less than 1000 points, which also happens to be the default turboThreshold). And here's the same fiddle, with more data, which breaks the tooltip formatter: http://jsfiddle.net/gparajon/5om258az/
Any workaround?
Thanks!
The error in the console is a bug and it is not really connect why you cannot access extra info in the formatter.
The difference between a chart and a stockchart is that a stockchart does data grouping, what means that in the formatter callback you receive grouped points which does not include extra data (how should they be grouped?).
example: https://jsfiddle.net/g04La2qh/1/
If you disable data grouping, you will receive non-grouped points with extra data.
dataGrouping: {
enabled: false
},
example: https://jsfiddle.net/g04La2qh/2/
Depending on the value of the highcharts range selector, I would like to change the data grouping. In my column chart, if one week is selected, there should be 7 bars, if one day is selected, there should be 24 bars, if one month is selected, there should be a bar for each day of the month.
There doesnt seem to be any way to supply a function inside the highchart configs to accomplish this, but I may be missing something.
My current plan was to handle a click event on the range selector to update the series data to contain the correct amount of points. But there may be a better way.
Thanks
There certainly are a bunch of options available in highstock for data grouping.
The primary one that you should look at is units. Here you can specify what kind of groups are allowed.
Top this up with groupPixelWidth and you have what you need, this width defines how small can a point in your chart be, if the number of points on the chart goes higher, the width per point decreases, once it goes below this threshold highcharts would force grouping. Keep this large enough to force grouping of next level, given you want not more than ~30 points on the screen.
dataGrouping: {
units: [
['hour', [1]],
['day', [1]],
['month', [1]],
['year', null]
],
groupPixelWidth: 100
}
#jsFiddle
Instead of using events you can combine range selector buttons with data grouping.
See: "Data grouping by buttons" in the API https://api.highcharts.com/highstock/rangeSelector.buttons
Example: https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/stock/rangeselector/datagrouping/
rangeSelector: {
allButtonsEnabled: true,
buttons: [{
type: 'month',
count: 3,
text: 'Day',
dataGrouping: {
forced: true,
units: [['day', [1]]]
}
}, {
type: 'year',
count: 1,
text: 'Week',
dataGrouping: {
forced: true,
units: [['week', [1]]]
}
}, {
type: 'all',
text: 'Month',
dataGrouping: {
forced: true,
units: [['month', [1]]]
}
}]
},
We tried a Hack around this, where we used Highstock's (Splinechart) RangeSelector, Event and DataGrouping. On click of weekly rangeselectorButton we catch this event through setExtremes. Post catching the event approximate it to "sum". If you are using two series than iterate the object.
events: {
setExtremes: function (e) {
if (e.rangeSelectorButton != undefined) {
var triger = e.rangeSelectorButton;
if (triger.type == 'week') {
$.each(this.series, function (index, obj) {
obj.options.dataGrouping.units[0] = ['week', [1]];
});
} else if (triger.type == 'day') {
$.each(this.series, function (index, obj) {
obj.options.dataGrouping.units[0] = ['day', [1]];
});
}
}
}
},
#fiddle
I'm in the process of creating a graph using HighStock (from HighCharts). I need to somehow convert the xAxis data to UTC objects but for some reason it is not graphing out the correct dates (it uses the default Jan1st).
If I import a list like ["2013-08-05 10:38:30","2013-08-06 10:38:30"] into javascript, how could I convert each element to a UTC object?
Many thanks!
$(function() {$('#container').highcharts('StockChart', {
rangeSelector : {
selected : 1
},
xAxis : {
data : ["2013-08-05 10:38:30","2013-08-06 10:38:30"],
type : 'datetime'
},
title : {
text : 'AAPL Stock Price'
},
series : [{
name : 'AAPL',
data : [10,20],
tooltip: {
valueDecimals: 2
}
}]
});
});
I advice to get your all string, then use i.e split function, and use Date.UTC() function. After it you can use this as x parameter in point in serie. Like:
series:[{
data:[[Date.UTC(2012,2,2),10],[Date.UTC(2013,2,2),3]]
}]
Data cannot be used in xAxis.