如何使用R dygraphs创建条形图和折线图?

时间:2017-06-16 21:15:40

标签: r dygraphs

我想使用dygraph创建一个条形图和折线图,这似乎应该可以基于“条形图和线条图”dygraphs示例here以及dyBarChart() {{ dygraphs包中提供了3}}。

使用自定义包装器,我可以创建一个条形图,所以我认为代码正常工作:

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()

custom plotter

我假设我可以使用dySeries()来自定义我想用线条/条显示的系列,但以下两种方法都没有。它们不会出错,但不会创建任何内容。我也不确定"linePlotter"是否是正确的绘图员名称,但不管怎样,我需要一些帮助。

# doesn't work
dygraph(lungDeaths) %>% 
  dyBarChart() %>% 
  dySeries("ldeaths", plotter = "linePlotter")

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

感谢。

3 个答案:

答案 0 :(得分:2)

有时候你很幸运...我几周前就已经做过同样的工作了,我发现文档不是很清楚如何做到这一点。但你自己很亲密。

如何操作 - 一步一步:

  1. 您必须为每个dyseries设置绘图仪
  2. dyseries命令中的plotter参数不带函数名称。但它需要是一个javascript函数作为纯文本
  3. 堆叠条形更容易。 Multibars需要一种方法将参数传递给javascript函数,你不能直接在包中做。所以我不得不做一个解决方法(至少我发现在R中没有更好的方法)。
  4. BTW,设置dyPlotter命令不起作用,因为它为绘图中的所有dySeries全局设置绘图仪。至少这就是我的想法。

    所以不用多说,这是我的代码。我添加了一些测试数据只是为了显示所有功能。

    测试数据:

    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")
    

    <强>功能

    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)
    }
    

    一些说明:

    dy_position执行所有绘图。它使用每个系列轴的单独绘图仪。

    需要

    reorder_xts以确保所有线条图都位于xts的右端。这是多杆图需要的。因为java脚本循环遍历所有系列(集合)以确定条的宽度,我们需要确保我们不循环遍历线图的系列。否则我们有额外的酒吧。

    multibar_combi_plotter正是如此。它需要一个数字参数lines_names并修改javascript字符串,以便它循环遍历所有绘图,除了line_names(即xts右边部分的最后一个系列)。注意%s命令的字符串中有几个sprintf!之后,它将绘图仪返回为character,用于dySeries参数。

    所有javascript代码都直接来自dygraphs文件夹中的示例。

    以下是一些例子......

    <强>示例:

    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)
    

答案 1 :(得分:0)

我不确定这正是你想要的。我的建议接近于条形图和线条图的组合,而不需要创建单独的函数。

您可以使用dySeries设置每个系列的绘图类型。您可以选择行图(默认),stepPlotstemPlot。此外,您可以设置为使用drawPointspointSize查看积分,您也可以选择使用fillGraph来填充图表。对于其他选项,请键入?dySeries

代码如下:

library(dygraphs)

lungDeaths <- cbind(ldeaths, mdeaths)

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

产生这个情节:

enter image description here

请让我知道这是否是你想要的。

答案 2 :(得分:0)

经过一番研究后,我认为这是最简单的。至少这对我来说就是这样。

您需要下载http://dygraphs.com/tests/plotters.html

处提供的“barseries.js”文件

然后代码就像这样

<a href="/link.html" class="gallery-item">
  <div style="background-image: url('https://picsum.photos/250/?random')" class="staticimage"></div>
  <div style="background-image: url('https://picsum.photos/251/?random')" class="hoverimage"></div>
</a>

产生这个结果

enter image description here