Reversed bullet chart in Highcharts - javascript

I started working with highcharts. Now a problem I am facing is that the bulletcharts can’t be used for a dataset that is in descending order.
For example say we want to plot the ranking of a few companies. In this case the ranking is better the lower it gets. So a Rank 10 is better than a Rank 15 and so on.
In this case I want my graph to get reversed. The target would be lets say 10. The min value would start from say 100 to 0. So you can see how this isnt possible.
P.S: I know the
reverse: true/false
property. But that simply flips the graph and I don’t want that/need that.
Thanks world.

You can add a second y-axis with the same extremes as the first one, but reversed. Next, hide the first y-axis, calculate mocked y and target values and finally, set a custom formatter function for tooltip to show original values.
const MAX = 300;
const TARGET = 50;
const Y = 25;
Highcharts.chart('container1', {
chart: {
inverted: true,
type: 'bullet',
},
yAxis: [{
visible: false,
min: 0,
max: MAX
}, {
min: 0,
max: MAX,
reversed: true,
...
}],
tooltip: {
formatter: function(tooltip) {
const point = this.point;
return `<span style='color: ${this.color}'>●</span> ${this.series.name}: <b>${point.originalY}</b>. Target: <b>${point.originalTarget}</b><br/>`
}
},
series: [{
data: [{
y: MAX - Y,
target: MAX - TARGET,
originalY: Y,
originalTarget: TARGET
}]
}]
});
Live demo: https://jsfiddle.net/BlackLabel/ve8hosd3/
API Reference: https://api.highcharts.com/highcharts/tooltip.formatter

Related

How to show Y axis ticks for every point in the graph

I'm using chartjs to display some data but I'm in trouble with the Y axis visualization. I want at every point in the graph a value in the Y axis. Right now the Y axis display value in steps of 10.
This is my actual yAxis configuration:
yAxes: [{
position: "left",
ticks: {
source:"data",
}
}]
This is the actual chart. I would like to display in the Y axis only the actual value of the points displayed. In the X axis this configuration works, the time is aligned with the points.
Expected:
You have to use the Axis Callbacks (docs), especially afterBuildTicks.
In my linked example (jsbin) I push 0 to my data because you can't use beginAtZero: true and remove all the duplicates in the array.
data.push(0); //if 'beginAtZero' is wanted
let uniqueData = data.filter((v, i, a) => a.indexOf(v) === i);
In the options you define the min and max values and the ticks in afterBuildTicks.
options: {
scales: {
yAxes: [{
ticks: {
autoSkip: false,
min: Math.min(...uniqueData),
max: Math.max(...uniqueData)
},
afterBuildTicks: function(scale) {
scale.ticks = uniqueData;
}
}]
}
}
You will have problems with overlapping ticks but I don't know a general way to prevent that and I don't know your specific use case.

How to count prediction (forecasting) in highchart only with data behind the last plotline?

I have a code for standard area-spline highchart where I made a function for prediction based on previous data. Prediction / forecasting is showing next 4 values in a trendline where the first prediction point is counting with real data, second point with real data plus first prediction point and the next two points about the same plus previous predictions. Otherwise it would be only a line with same values. But my data are increasing so the forecasting must be about the same.
Data in highchart are connected to Microsoft SQL Server.
Prediction is based on this code, just with few changes:
Forecast formula from Excel in Javascript
The highchart is now showing increasing data (values of resistance) as a decimal in yAxis and datetime in xAxis. Prediction is working as well but the thing is that not all data are relevant.There is always a point which is very different (lower than previous) and thats the place from where I need to count new prediction. The plotline is generated in the last high value, then starting the new (low) - and that is from where I need to count.
So here is what I do have:
-the function 'average' is counting average from values
-second function 'forecast' as you can expect is counting the forecasting (based on the code from link above)
-third function 'test' is already putting all together
-the 'results' (2,3,4) are the counted points of prediction
-'vlastnidata' are the data from mssql
-'datumek' is for the date
Now the condition for plotline (as you can see there) is that the previous point in chart must be 20 higher and then the plotline is generated - this is also working, just need to find a way how to count only with new data behind the plotline.
And here you can reach the connection function to mssql in php - if needed
Is there a way how to dynamically create a plotline in highchart when the value is lower than previous one?
As I said everything is working, plotlines and the prediction. But to see clear prediction I need to count only with relevant data.
Hope everything is clear. Thank you in advance for any recommendations.
function average(ar)
{
var r=0;
for (i=0;i<ar.length;i++)
{
r = r+ar[i];
}
return r/ar.length;
}
function forecast(x, ky, kx)
{
var i=0, nr=0, dr=0,ax=0,ay=0,a=0,b=0, result=0;
ax=average(kx);
ay=average(ky);
for (i=0;i<kx.length;i++)
{
nr = nr + ((kx[i]-ax) * (ky[i]-ay));
dr = dr + ((kx[i]-ax)*(kx[i]-ax))
}
b=nr/dr;
a=ay-b*ax;
result = (a+b*x);
return result;
}
function test(container,nazev,rtop,vlastnidata,colorSeries)
{
var result = 0, result2 = 0, result3 = 0, result4 = 0, datumek=[],hodnoty=[];
for (a=0;a<vlastnidata.length;a++)
{
datumek[a]=vlastnidata[a][0];
hodnoty[a]=vlastnidata[a][1];
}
kalkulace=(datumek[vlastnidata.length-1]-datumek[vlastnidata.length-2]);
hodnoty_nove=hodnoty;
datumek_nove=datumek;
result = forecast((datumek[vlastnidata.length-1]+kalkulace), hodnoty, datumek);
hodnoty_nove[hodnoty_nove.length]=result;
datumek_nove[datumek_nove.length]=(datumek[vlastnidata.length-1]+kalkulace);
result2 = forecast((datumek[vlastnidata.length-1]+2*kalkulace), hodnoty_nove, datumek_nove);
hodnoty_nove[hodnoty_nove.length]=result2;
datumek_nove[datumek_nove.length]=(datumek[vlastnidata.length-1]+2*kalkulace);
result3 = forecast((datumek[vlastnidata.length-1]+3*kalkulace), hodnoty_nove, datumek_nove);
hodnoty_nove[hodnoty_nove.length]=result3;
datumek_nove[datumek_nove.length]=(datumek[vlastnidata.length-1]+3*kalkulace);
result4 = forecast((datumek[vlastnidata.length-1]+4*kalkulace), hodnoty_nove, datumek_nove);
Highcharts.chart(container, {chart: {type: 'areaspline',
events: {
load:function(){
let points = this.series[0].points;
let plotLines = [];
console.log(this)
let previousPoint = points[0];
points.forEach(function(point) {
if(point.y < previousPoint.y/100*80) {
plotLines.push({
value: previousPoint.x,
color: 'red',
width: 3
});
}
previousPoint = point;
});
this.xAxis[0].update({
plotLines: plotLines
})
}
}
},
title: {text: 'Average of resistance per month, '+rtop},
legend: {layout: 'vertical',
align: 'left',
verticalAlign: 'top',
x: 150,
y: 100,
floating: true,
borderWidth: 1,
backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF'},
xAxis: { type: 'datetime'},
yAxis: {title: {text: 'Resistance: in ohms'}},
tooltip: {shared: true,valueSuffix: ' ohms',valueDecimals: 2},
credits: {enabled: false},
plotOptions: {areaspline: {fillOpacity: 0.5}},
series: [{ name: nazev,
color: colorSeries,
data: vlastnidata},
{name: 'Prediction',
color: '#001a33',
data: [[(datumek[vlastnidata.length-1]+kalkulace),result], [(datumek[vlastnidata.length-1]+2*kalkulace),result2], [(datumek[vlastnidata.length-1]+3*kalkulace),result3], [(datumek[vlastnidata.length-1]+4*kalkulace),result4]]
}]
});
}

C3 Bar Graph x-axis labels are too congested

I have created a Bar graph using C3 JS plugin, The graph is working fine but the problem is with the x-axis labels looks too congested like as shown below
Working JSFiddle
My Code is as given below
var chart = c3.generate({
bindto: "#chart",
data: {
x : 'x',
columns: [
['x', "2016-04-01","2016-04-08","2016-04-15","2016-04-22","2016-04-29","2016-05-06","2016-05-13","2016-05-20","2016-05-27","2016-06-03","2016-06-10","2016-06-17","2016-06-24","2016-07-09","2016-07-10","2016-07-11","2016-07-12","2016-07-13","2016-07-15","2016-07-16","2016-07-17","2016-07-18","2016-07-19","2016-07-20","2016-07-21","2016-07-22","2016-07-23","2016-07-24","2016-07-25","2016-07-26","2016-07-27","2016-07-28","2016-07-29","2016-07-30","2016-07-31","2016-08-01","2016-08-02","2016-08-03","2016-08-04","2016-08-05","2016-08-06","2016-08-07","2016-08-08","2016-08-09","2016-08-10","2016-08-11","2016-08-12","2016-08-13","2016-08-14","2016-08-15","2016-08-16","2016-08-17","2016-08-18","2016-08-19","2016-08-20","2016-08-21","2016-08-22","2016-08-23","2016-08-24","2016-08-25","2016-08-26","2016-08-27","2016-08-28","2016-08-29","2016-08-30","2016-08-31","2016-09-01","2016-09-02","2016-09-03","2016-09-04","2016-09-05","2016-09-06","2016-09-07","2016-09-08","2016-09-09","2016-09-10","2016-09-11","2016-09-12","2016-09-13","2016-09-14","2016-09-15","2016-09-16","2016-09-17","2016-09-18","2016-09-19","2016-09-20","2016-09-21","2016-09-22","2016-09-23","2016-09-24","2016-09-25","2016-09-26","2016-09-27","2016-09-28","2016-09-29","2016-09-30","2016-10-01","2016-10-02","2016-10-03","2016-10-04","2016-10-05","2016-10-06","2016-10-07","2016-10-08","2016-10-09","2016-10-10","2016-10-11","2016-10-12","2016-10-13","2016-10-14","2016-10-15","2016-10-16","2016-10-17","2016-10-18","2016-10-19","2016-10-20","2016-10-21","2016-10-22","2016-10-23","2016-10-24","2016-10-25","2016-10-26","2016-10-27","2016-10-28","2016-10-29","2016-10-30","2016-10-31","2016-11-01","2016-11-02","2016-11-03","2016-11-04","2016-11-09"],
['pv1', 2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2696,2696,2696,2696,2696,2696,2696,2696,2696,2696,2696,2696,2696,2696,2696,2696,2748,2748,2694,2694,2694,2694,2694,2694,2694,2668,2668,2668,2668,2576,2572,2572,3043,3084,3084,3084,3084,3084,3156,3521,3521,3550,3542,3542,3573,3580,3629,3579,3584,3542,2757,2791,2696,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3414,3414,3414,3414,3414,3414,3414,3414,3414,3414,3414,3414,3414,3369,3376,3371,3373,3371,3379,3363,3373,3347,3348,3382,3402,3410,3434,2579,2579,2369],
['pv2', 1750,1750,1750,1750,1825,1850,1975,2150,2375,2425,2475,2500,2500,2087,2087,2087,2087,2091,2087,1767,1767,1767,1633,1498,1498,1642,1637,1633,1609,1841,1713,1702,1862,1888,1888,1888,1949,1976,1977,2014,2014,2014,1946,1966,1973,2224,2252,2318,2318,2318,2327,2373,2513,2535,2543,2534,2539,2823,2849,2990,3142,3142,3108,2513,2687,2678,2856,2860,2861,2862,2866,2869,2870,2875,2874,2874,2874,2879,2885,2886,2883,2889,2896,2895,2899,2903,2909,2911,2913,2913,2913,2916,2922,2933,2937,2943,2942,2943,2947,1811,1826,1837,1840,1840,1841,1843,1511,1854,1853,1851,1852,1853,1849,1852,1874,1857,1883,1886,1888,1904,1903,1924,1947,2060,2068,2068,2082,1582,1344,836,839,788]
],
type: 'bar'
},
axis: {
x: {
type: 'category',
tick: {
rotate: -60,
multiline: false
},
height: 130
}
}
});
Can anyone please tell me some solution for this
What I did to solve it
I have used timeseries type instead of category type, after that the label issue got resolved but the graph was been plottted with more white spaces for the month of march like as shown below
Working JSFiddle
You can use c3's tick count setting for this, so here we say 20 labels.
However there is an added gotcha in that ticks that now resolve to a fractional category value won't show - i.e. the 2nd equally spaced tick out of 20 may be the 2.6667th element in the x category axis - so you need to have a little format function that adjusts for this, otherwise you just get the end and start labels. (Or you could figure out a tick count that divides into your data count + 1 as a whole number.)
tick: {
format: function (x) {
var cats = this.api.categories();
return cats[Math.round(x)];
},
count: 20,
rotate: -60,
multiline: false
},
http://jsfiddle.net/fz0t10yb/7/
One of the possible solution could be to use x-axis labels at required indexes only & leaving others blank.
['x', "2016-04-01","","","","2016-04-29","","","",...]
['pv1', 2500,2500,2500,2500,2500,2500,2500,2500,...]
['pv2', 1750,1750,1750,1750,1825,1850,1975,2150,...]
You can position labels so that it would capture the date and at same time it looks good also.

Flot Bubbles Plugin - Bubble Size

I am using the Bubbles plugin with the Flot charting library for JQuery. The data I have is dynamic and can be quite varied within the X, Y, and Z values. The main issue I am having is the size of the bubbles. If the X and Y values are somewhat close to each other but the Z value is much larger the bubble simply takes over the chart. Setting the axis min and max for the X and Y axes helps a bit but not in every case. I have tried to look for other options and settings but did not find anything useful. Is there any type of way to control the size of the bubble?
For instance Flex used to automatically create bubble sizes relative to the screen and axes where Flot seems to always set the bubble size to the same scale as the X and Y values. I have included just a sample of data. I would like to continue to use Flot as the plugin because I have many other chart types in my application and would like to use the same code base. However if there is another plugin that would be better I am open to ideas. Thanks!
https://jsfiddle.net/llamajuana/zd4hd7rb/
var d1 = [[30,339,139856], [30, 445,239823], [30,1506,127331]];
var options = {
series: {
//color: '#CCC',
color: function(x, y, value) {
var red = 55 + value * 10;
return 'rgba('+red+',50,50,1)';
},
bubbles: {
active: true,
show: true,
fill: true,
linewidth: 0,
bubblelabel: {
show: true
},
highlight: {
show: true,
opacity: 0.3
}
}
},
grid:{
hoverable: true,
clickable: true
},
tooltip: {
show: true,
content: "x: %x | y: %y | value: %ct"
}
};
var p4 = $.plot( $("#plot"), [d1], options );
You could try logarithmic scaling.
For the x- and y-axis you can do this using the transform property in the axis options or changing the data before drawing the plot.
For the bubbles you have to do this by hand, either by changing the data before drawing or by replacing the drawbubble function of the bubbles plugin (see the User draw example here).
See this fiddle for the full example. Changes from your fiddle:
1) You could change this directly in the bubbles plugin, if you wanted.
// index of bubbles plugin is dynamic, you better search for it
var defaultBubbles = $.plot.plugins[1].options.series.bubbles.drawbubble;
var logBubbles = function(ctx, serie, x, y, v, r, c, overlay){
defaultBubbles(ctx, serie, x, y, v, Math.log(r), c, overlay);
}
2) In the series options:
xaxis: {
transform: function (v) {
return Math.log(v);
},
inverseTransform: function (v) {
return Math.exp(v);
}
},
yaxis: {
transform: function (v) {
return Math.log(v);
},
inverseTransform: function (v) {
return Math.exp(v);
}
},
3) In the radiusAtPoint() function in the bubbles plugin:
// added Math.log function here too
return parseInt(series.yaxis.scale * Math.log(series.data[radius_index][2]) / 2, 0);

JQplot barRenderer "y-axis" values start from negative values

Does anyone know how to make "y-axis" values start from 0 in Jqplot....by default it starts with negative values for eg: -500, 0, 500, 1000 and so on....Please help
Set min: object (minimum) to 0 within axes: object
$(document).ready(function(){
// your code here... //
axes:{
yaxis: {min:0}
}
})
As rsapru suggested, a max: object (maximum) value is recommended to bound the graph to your preferred range. For example, if you wanted the minimum to be 0 and maximum to be 7500
axes:{
yaxis: {min:0, max: 7500}
}
If you want to specify the graduations of the ticks you can do so manually by specifying ticks with the ticks: object or have jqPlot calculate tick spacing automatically (nothing other than min and max objects would be needed in that case) or by your specific number of ticks (using numberTicks: object)
Example: For tick 100 units apart, from 0 to 1000, using 11 ticks (0,100,200,300,400,500,600,700,800,900,1000) jqPlot automatic calculation:
axes:{
yaxis: {min:0, max: 1000, numberTicks: 11}
}
Example: For tick 100 units apart, from 0 to 1000, using 11 ticks (0,100,200,300,400,500,600,700,800,900,1000) manual specification:
axes:{
yaxis: {min:0, max: 1000, Ticks: [[0],[100],[200],[300],[400],[500],[600],[700],[800],[900],[1000]]}
}
var plot2 = $.jqplot ('chartdiv', getRequestStats(), {
// Give the plot a title.
title: 'Daily Request Status',
// You can specify options for all axes on the plot at once with
// the axesDefaults object. Here, we're using a canvas renderer
// to draw the axis label which allows rotated text.
axesDefaults: {
labelRenderer: $.jqplot.CanvasAxisLabelRenderer
},
// An axes object holds options for all axes.
// Allowable axes are xaxis, x2axis, yaxis, y2axis, y3axis, ...
// Up to 9 y axes are supported.
axes: {
// options for each axis are specified in seperate option objects.
xaxis: {
label: "Hour",
// Turn off "padding". This will allow data point to lie on the
// edges of the grid. Default padding is 1.2 and will keep all
// points inside the bounds of the grid.
pad: 0
},
yaxis: {
label: "Count",
pad: 0
}
}
});
pad: 0 will star the Y axis to start from 0.
Refer to http://www.jqplot.com/docs/files/jqPlotOptions-txt.html
set yaxis: {min: 0, max: 500, numberTicks:5}
add yaxis: {min:0} in your yaxis
The following solution work for me.
-> Add zero value in array also.
-> set the data render to $.jqplot.CanvasAxisLabelRenderer
yaxis: {
renderer: $.jqplot.CanvasAxisLabelRenderer
.....
}
Thanks
Adnan
Add the following to the script:
yaxis: {
minimum:0
}
in your yaxis. I tried it and it works.

Categories

Resources