The standard example of the rChartsCalendar works with defaults of the JS calendar as shown in http://kamisama.github.io/cal-heatmap/
The example code below works fine:
dat <- read.csv('http://t.co/mN2RgcyQFc')[,c('date', 'pts')]
library(rChartsCalendar)
r1 <- plotCalMap(x = 'date', y = 'pts',
data = dat,
domain = 'month',
start = "2012-10-27",
legend = seq(10, 50, 10),
itemName = 'point',
range = 7
)
The problem comes when I try to set nested attributes in R, for example to define the position and the offset of the label. In HTML / JS it would be as easy as writing following code, but how can I define from R the values for the offset for the label?
var cal = new CalHeatMap();
cal.init({
itemSelector: "#label-d",
domain: "day",
range: 2,
displayLegend: false,
label: {
position: "right",
width: 46,
offset: {x: 10, y: 30}
}
});
I tried using the method set and passing the json piece as string, but then it gets rendered with the quotes in HTML/JS, which obviously doesn't work
r1$set(label="{position: 'left', width: 110, offset: { x: 20, y: 12 } }")
Update: I got it working using a combination of "c" and "list" as follows:
label= c( list(position = 'left'),list( width = 110),list(offset = list (x=20,y=30))),
It's not very straight away, but I felt like sharing it because it took me a lot of time
Related
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
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]]
}]
});
}
I have a flask app that I am working on. I'm using a js gauge system and I want the value to be a variable that I scrape off of a web page. I scrape the page just fine and return the values I want but when I give that value to the script it returns NaN%. I can cal the variable in the html section just fine.
JS Snippet
var g2 = new JustGage({
id: 'g2',
value: '{{a0}}',
min: 0,
max: 100,
symbol: '%',
pointer: true,
pointerOptions: {
toplength: -15,
bottomlength: 10,
bottomwidth: 12,
color: '#8e8e93',
stroke: '#ffffff',
stroke_width: 3,
stroke_linecap: 'round'
},
gaugeWidthScale: 1,
counter: true
});
Flask Part
g_data = ast.literal_eval(soup.get_text())
a0 = g_data['ainputs'][3:8]
a1 = g_data['ainputs'][12:17]
a2 = g_data['ainputs'][21:26]
a3 = g_data['ainputs'][30:35]
a4 = g_data['ainputs'][39:45]
Now I have tried to use float and int on the variable, but neither one returns anything besides NaN%. If I put the variable in the value spot without quotes, none of the gauges display anything.
Apparently I wasn't passing the variables to the right view. I am sorry. Just using {{a0}} works now.
I am developing in Javascript to render a table using a DataTables (Table plug-in for jQuery). I am also using Bootstrap Multiselect (https://github.com/davidstutz/bootstrap-multiselect) to filter the table. I would like to re-render my BokehJS plot everytime the table is re-drawn. I have hooked up the correct calls but I am also calling Bokeh.Plotting.show to re-render the graph. This forces me to remove the last created div to avoid multiple graphs plotted. I am new to the JS side of Bokeh and wanted to understand if there is a cleaner method to update the plot in JS?
var eventFired = function ( type ) {
//var n = $('#demo_info')[0];
//n.innerHTML += '<div>'+type+' event - '+new Date().getTime()+'</div>';
//n.scrollTop = n.scrollHeight;
var plt = Bokeh.Plotting;
// set up some data
var M = 25;
var xx = [];
var yy = [];
var colors = [];
var radii = [];
for (var y = 0; y <= M; y += 4) {
for (var x = 0; x <= M; x += 4) {
xx.push(x * (Math.random() +0.5));
yy.push(y * (Math.random() +0.5));
colors.push(plt.color(50+8*x, 30+8*y, 150));
radii.push(Math.random() * 0.4 + 1.7)
}
}
// create a data source
var source = new Bokeh.ColumnDataSource({
data: { x: xx, y: yy, radius: radii, colors: colors }
});
// make the plot and add some tools
var tools = "pan,crosshair,wheel_zoom,box_zoom,reset,save";
var p = plt.figure({ title: type+' event - '+new Date().getTime(),
height: 300,
width: 300,
tools: tools });
// call the circle glyph method to add some circle glyphs
var circles = p.circle({ field: "x" }, { field: "y" }, {
source: source,
radius: radii,
fill_color: colors,
fill_alpha: 0.6,
line_color: null
});
//remove old plot on update conditions
$('.bk-root').remove();
// Show the plot, appending it to the end of the current
// section of the document we are in.
Bokeh.Plotting.show(p, document.getElementById('myplot'));
//To Do: add in transition to improve the UI appearance
}
And here is the the datatable setting up the call back to the BokehJS script.
</script>
$('#table').DataTable({
responsive: {
details: {
display: $.fn.dataTable.Responsive.display.modal( {
header: function ( row ) {
var data = row.data();
return 'Details for '+data[0]+' '+data[1];
}
} ),
renderer: $.fn.dataTable.Responsive.renderer.tableAll( {
tableClass: 'table'
} )
}
},
paginate: false,
info: false,
paging: true,
autoWidth: true,
dom: '<"dt-buttons">Bf<"clear">lirtp',
"buttons": [ 'copy', 'csv', 'excel' ],
}).on( 'draw.dt', function () { eventFired( 'Draw' ); } );
Lastly, is there a good method to update the plot via a transition effect to improve the appearance of the re-plotting?
I eventually figured out all of the components in the process in a modified use case compared to the one shown above. In my present approach I needed to utilize my source data and emit a 'change' trigger.
source.data.factors = [my new factor list]
source.trigger('change');
The new factor list based on the jQuery datatable can be obtained as followed.
$('mytable').DataTable().columns(0, {search: 'applied'}).data()[0]
Also in my use case I am working with a categorical axis. In my specific use case, my factors will dynamically change upon redraw of the graph. This can be achieved using the plot's attributes.
p.attributes.x_range.factors = [ my new factor list from my updated source data]
There is also no need to remove the old plot, and the added plus is the redraw is very fast for my simple plots.
I use google's chart javascript api to show some data. The data contains "0" / "null" values.
//...
totalpt1.setValue(154, 2, 1310799);
totalpt1.setValue(155, 2, 1313905);
totalpt1.setValue(156, 2, null);
totalpt1.setValue(157, 2, 1320264);
totalpt1.setValue(158, 2, 1323102);
//...
var chart11 = new google.visualization.LineChart(document.getElementById('chart_totalpostthreads'));
chart11.draw(totalpt, {width: 600, height: 340, interpolateNulls:true, legend: 'bottom', title: 'Total Posts'});
The result is this:
I have set interpolateNulls to true. But the graph is still not "smoothed". How can I prevent those single drop outs? I thought this is what the interpolate option was for...
Null and 0 are different values.
You should use:
totalpt1.setValueNull(156, 2);