How do you create a bar and line graph with R dygraphs?

I would like to create a chart and line chart using dygraphs, which seems to be possible based on the dygraphs "Bar and Line Chart" example here and the dyBarChart() custom plotter provided in the dygraphs package.

Using a custom wrapper, I can create a barcode, so I think this code works:

 library(dygraphs) dyBarChart <- function(dygraph) { dyPlotter( dygraph = dygraph, name = "BarChart", path = system.file("examples/plotters/barchart.js",package = "dygraphs") ) } lungDeaths <- cbind(ldeaths, mdeaths) dygraph(lungDeaths) %>% dyBarChart() 

enter image description here

I suggested that then I could use dySeries() to set up a series that I wanted to show with a line / line, but none of the following works. They do not fail, but nothing is created. I'm also not sure if "linePlotter" is the correct name for the plotter, but in any case I need a little help.

 # doesn't work dygraph(lungDeaths) %>% dyBarChart() %>% dySeries("ldeaths", plotter = "linePlotter") # also doesn't work: dygraph(lungDeaths) %>% dySeries("ldeaths", plotter = "dyBarChart") %>% dySeries("mdeaths", color = "blue") 

Thanks.

+3
source share
3 answers

Sometimes you are lucky ... I worked on the same thing a few weeks ago, and I found that the documentation is not entirely clear how to do this. But you were pretty close.

How to do it - step by step:

  • You need to install a plotter for each dyseries
  • The plotter argument in the dyseries command does not accept function names. But it should be a javascript function as plain text.
  • Stacking bars is easier. Multi-bars need a way to pass an argument to a javascript function that you cannot do directly in the package. So I had to make a workaround (at least I did not find a better way to do this in R).

BTW, setting the dyPlotter command dyPlotter not work, because it sets the plotter globally for all dySeries on the chart. At least that's what I think.

So, without much ado, here is my code. I added some more test data to show all the features.

Test data:

 library(xts) library(dygraphs) test<-xts(matrix(rnorm(100*4), ncol=4, nrow=100), order.by=seq.POSIXt(as.POSIXct("2017-01-01 00:00", tz="UTC"),by=3600, length.out = 100)) colnames(test)<-c("Series_A","Series_B", "Series_C", "Series_D") 

Functions:

 dy_position<-function(data_final, plot_title, y2_names=NULL, y1_label, y2_label, y1_step=F, y2_step=F, stacked=T){ data_final<-reorder_xts(data_final, y2_names) #reorder necessary so that all y2 are at the right end of the xts. Needed for the multibar plot dyg <- dygraphs::dygraph(data_final, main=plot_title) dyg <- dygraphs::dyAxis(dyg, "x", rangePad=20) dyg <- dygraphs::dyAxis(dyg, "y", label = y1_label, axisLabelWidth = 90) y1_names<-colnames(data_final)[!(colnames(data_final) %in%y2_names)] if (length(y1_names)==1){ stacked<-T #in this case only stacking works } if (stacked){ dyg <- dygraphs::dyOptions(dyg,stepPlot=y1_step,stackedGraph = T) for(i in seq_along(y1_names)) { dyg <- dygraphs::dySeries(dyg, y1_names[i], axis = "y", strokeWidth = 1.5, stepPlot = y1_step, plotter=" function barChartPlotter(e) { var ctx = e.drawingContext; var points = e.points; var y_bottom = e.dygraph.toDomYCoord(0); ctx.fillStyle = e.color; // Find the minimum separation between x-values. // This determines the bar width. var min_sep = Infinity; for (var i = 1; i < points.length; i++) { var sep = points[i].canvasx - points[i - 1].canvasx; if (sep < min_sep) min_sep = sep; } var bar_width = Math.floor(2.0 / 3 * min_sep); // Do the actual plotting. for (var i = 0; i < points.length; i++) { var p = points[i]; var center_x = p.canvasx; ctx.fillRect(center_x - bar_width / 2, p.canvasy, bar_width, y_bottom - p.canvasy); ctx.strokeRect(center_x - bar_width / 2, p.canvasy, bar_width, y_bottom - p.canvasy); } }") } } else { dyg <- dygraphs::dyOptions(dyg,stepPlot=y1_step) for(i in seq_along(y1_names)) { #plotter in function dyg <- dygraphs::dySeries(dyg, y1_names[i], axis = "y", strokeWidth = 1.5, stepPlot = y1_step, plotter =multibar_combi_plotter(length(y2_names))) } } # put stuff on y2 axis dyg <- dygraphs::dyAxis(dyg, "y2", label = y2_label, independentTicks = T) for(i in seq_along(y2_names)) { dyg <- dygraphs::dySeries(dyg, y2_names[i], axis = "y2", strokeWidth = 1.5, stepPlot = y2_step) } return(dyg) } #we need to take into account all values and then leave out the ones we do not like multibar_combi_plotter<-function(num_values){ #plotter function plotter_text<-"function multiColumnBarPlotter(e) { // We need to handle all the series simultaneously. if (e.seriesIndex !== 0) return; var g = e.dygraph; var ctx = e.drawingContext; var sets = e.allSeriesPoints; var y_bottom = e.dygraph.toDomYCoord(0); // Find the minimum separation between x-values. // This determines the bar width. var min_sep = Infinity; for (var j = 0; j < sets.length-%s; j++) { var points = sets[j]; for (var i = 1; i < points.length; i++) { var sep = points[i].canvasx - points[i - 1].canvasx; if (sep < min_sep) min_sep = sep; } } var bar_width = Math.floor(2.0 / 3 * min_sep); var fillColors = []; var strokeColors = g.getColors(); for (var i = 0; i < strokeColors.length; i++) { fillColors.push(strokeColors[i]); } for (var j = 0; j < sets.length-%s; j++) { ctx.fillStyle = fillColors[j]; ctx.strokeStyle = strokeColors[j]; for (var i = 0; i < sets[j].length; i++) { var p = sets[j][i]; var center_x = p.canvasx; var x_left = center_x - (bar_width / 2) * (1 - j/(sets.length-%s-1)); ctx.fillRect(x_left, p.canvasy, bar_width/sets.length, y_bottom - p.canvasy); ctx.strokeRect(x_left, p.canvasy, bar_width/sets.length, y_bottom - p.canvasy); } } }" custom_plotter <- sprintf(plotter_text, num_values, num_values, num_values) return(custom_plotter) } reorder_xts<-function(xts_series,line_names){ bar_names<-colnames(xts_series)[!(colnames(xts_series)%in%line_names)] xts_series<-xts_series[,c(bar_names,line_names)] return(xts_series) } 

Some Explanation:

dy_position runs the entire chart. It uses separate plotters for each series.

reorder_xts requires all line graphs to be on the right end of xts. This is necessary for a multi-byte plot. Since the java script loops through all the series (sets) in order to determine the width of the bars, and we need to make sure that we do not iterate over the lines, which are string charts. Otherwise, we have additional bars.

multibar_combi_plotter does just that. It takes a numerical parameter lines_names and modifies the javascript line so that it intersects all the charts except line_name (i.e. the last series on the right side of the xts). Note the few small %s in the line for the sprintf command! Later, he returns as a plotter character for dySeries argument.

All javascript code is taken directly from the examples in the dygraphs folder.

Here are some examples ...

<strong> Examples:

 dy_position(test,plot_title = "Test1", y2_names = c("Series_C","Series_D"),y1_label = "Axis1", y2_label = "Axis2", stacked=F) dy_position(test,plot_title = "Test1", y2_names = c("Series_C","Series_D"),y1_label = "Axis1", y2_label = "Axis2", stacked=T) dy_position(test,plot_title = "Test1", y2_names = c("Series_B","Series_C","Series_D"),y1_label = "Axis1", y2_label = "Axis2", stacked=T) dy_position(test,plot_title = "Test1", y2_names = c("Series_D"),y1_label = "Axis1", y2_label = "Axis2", stacked=F) dy_position(test,plot_title = "Test1", y2_names = c("Series_D"),y1_label = "Axis1", y2_label = "Axis2", stacked=T) dy_position(test,plot_title = "Test1", y2_names = NULL ,y1_label = "Axis1", y2_label = "Axis2", stacked=F) dy_position(test,plot_title = "Test1", y2_names = NULL ,y1_label = "Axis1", y2_label = "Axis2", stacked=T) 
+2
source

I am not sure if this is exactly what you want. What I am proposing is approaching a combination of a line graph and a line graph without the need to create a separate function.

You can set the type of graph for each series, dySeries . You can choose between line (default), stepPlot and stemPlot . In addition, you can set points with drawPoints and pointSize , you can also choose to fill the graph or not fillGraph . For other options, enter ?dySeries

The code is as follows:

 library(dygraphs) lungDeaths <- cbind(ldeaths, mdeaths) dygraph(lungDeaths, main = "Main Title") %>% dySeries("ldeaths", drawPoints = FALSE) %>% dySeries("mdeaths", stepPlot = TRUE, fillGraph = TRUE) 

Yielding to this plot:

enter image description here

Please let me know if you want this.

0
source

After a little research, I think that would be easiest. At least, as it seems to me.

You will need to download the "barseries.js" file, available at http://dygraphs.com/tests/plotters.html

Then the code will look like this

 library(dygraphs) dyBarSeries <- function(dygraph, name, ...) { file <- "plotters/barseries.js" #you need to link to the downloaded file plotter_ <- paste0(readLines(file, skipNul = T), collapse = "\n") dots <- list(...) do.call('dySeries', c(list(dygraph = dygraph, name = name, plotter = plotter_), dots)) } lungDeaths <- cbind(ldeaths, mdeaths) dygraph(lungDeaths) %>% dyBarSeries("ldeaths") %>% dySeries("mdeaths") 

Satisfying this result

enter image description here

0
source

Source: https://habr.com/ru/post/1276035/


All Articles