R Highcharter:使用同步 zoom/tooltip 分隔图例或多个图表的巧妙方法?

R Highcharter: Clever way to separate legends or multiple charts with synchronized zoom/tooltip?

我的问题与我使用 highstock 绘制多个堆叠的 y 轴的情况有关,例如此处的最后一个示例:http://jkunst.com/highcharter/highstock.html

我希望每个 y 轴都有单独的图例,但进行一些挖掘后发现 highcharts 似乎只能有一个图例 (Highcharts multiple legends)。

然后我想也许我可以使用注释来模仿所需的图例。但是绘制彩色线段会很混乱,因为它们会显示为系列(尽管我想我可以只使用彩色文本来指示哪个系列是哪个系列)。

在 highcharts 中使用多个 y 轴时,是否有巧妙的方法来绕过 one-legend 限制?

如果不是,那么如果我绝对需要有单独的图例,我似乎不得不使用多个堆叠图表。在这种情况下,我需要在这些多个图表中同步缩放和工具提示。有很多关于如何通过 javascript 执行此操作的信息(我的经验有限),但似乎也经常出现同步缩放和工具提示的问题。

我想知道是否有任何关于如何在 R highcharter 中跨多个图表同步缩放和工具提示的示例(我已经搜索了 high 和 low 并且没有找到任何)?

我将非常感谢这里的社区可能有的任何见解。

library(highcharter)
library(gplots)

dates   <- seq(as.Date('2015-04-24'),as.Date('2020-04-24'),1)
nDates  <- NROW(dates)
x11     <- xts(100 * cumprod(1 + 0.0010 * (1 + 0.0002 * rnorm(nDates))), dates)
x12     <- xts(100 * cumprod(1 + 0.0012 * (1 + 0.0001 * rnorm(nDates))), dates)
x2      <- xts(100 * runif(nDates), dates)
x31     <- xts(-1 + 2 * runif(nDates), dates)
x32     <- xts( 1 - 2 * runif(nDates), dates)

glc     <- col2hex('gray65') #gridLineColor)

hc <- highchart(type = 'stock') %>% 
        hc_chart(marginLeft = 75, marginRight = 75) %>% 
        hc_title(text = 'Example', align = 'center', verticalAlign = 'top', style = list(fontWeight = 'bold', fontSize = '20px')) %>%
        hc_rangeSelector(selected = 7) %>%
        hc_navigator(series = list(color = hex_to_rgba('black',1))) %>%
        hc_xAxis(type = 'datetime') %>% 
        hc_yAxis_multiples( 
                            #yAxis = 0, plot x11 and x12 here
                            list(top = "0%",  height = '60%', opposite = FALSE, type = 'logarithmic', showLastLabel = TRUE, allowDecimals = FALSE, 
                                     labels = list(align = 'right', x = -10, format = '{value}%', distance = 0), gridLineDashStyle = 'Dot', gridLineColor = glc, startOnTick = FALSE, endOnTick = TRUE),

                            #yAxis = 1 to duplicate axis labels on opposite side    
                            list(top = "0%",  height = '60%', opposite = TRUE, type = 'logarithmic', showLastLabel = TRUE, allowDecimals = FALSE, linkedTo = 0, opposite = TRUE, 
                                labels = list(align = 'right', x =  50, format = '{value}%', distance = 0), gridLineDashStyle = 'Dot', gridLineColor = glc, startOnTick = FALSE, endOnTick = TRUE),

                            #yAxis = 2, just to separate the charts
                            list(top = '60%', height = '5%'),

                            #yAxis = 3, plot x2 here
                            list(top = '65%', height = '15%', opposite = FALSE, tickPositions = c(0, 33, 67, 100), gridLineDashStyle = 'Dot', gridLineColor = glc, showLastLabel = TRUE,
                                    labels = list(align = 'right', x= 35, format = '{value}%', distance = 0)),

                            #yAxis = 4, to duplicate the axis labels on the opposite side
                            list(top = '65%', height = '15%', linkedTo = 3, opposite = TRUE, tickPositions = c(0, 33, 67, 100), gridLineDashStyle = 'Dot', gridLineColor = glc, showLastLabel = TRUE,
                                        labels = list(align = 'right', x= 50, format = '{value}%', distance = 0)),

                            #yAxis = 5, to separate the charts
                            list(top = '80%', height = '5%'),

                            #yAxis = 6, plot x31, x32, x33 here
                            list(top = '85%', height = '15%', opposite = FALSE, tickPositions = c(-2, -1, 0, 1, 2), gridLineDashStyle = 'Dot', gridLineColor = glc, showLastLabel = TRUE,
                                    labels = list(align = 'right', x = 30, distance = 0, format = '{value:.1f}'), plotLines = list(list(color = "black", width = 2, value = 0))),

                            #yAxis = 7, to duplicate the axis labels on the opposite side
                            list(top = '85%', height = '15%', linkedTo = 6, opposite = TRUE, tickPositions = c(-2, -1, 0, 1, 2), gridLineDashStyle = 'Dot', gridLineColor = glc, showLastLabel = TRUE,
                                        labels = list(align = 'right', x = 50, distance = 0, format = '{value:.1f}'))

                          ) %>%


            #Chart 1
            hc_add_series(x11, yAxis = 0, color = 'navy',   name = 'Series 11', tooltip = list(valueDecimals = 1, valueSuffix = '%')) %>%  
            hc_add_series(x12, yAxis = 0, color = 'green',  name = 'Series 12', tooltip = list(valueDecimals = 1, valueSuffix = '%')) %>% 

            #Chart 2
            hc_add_series(x2, yAxis = 3, color = 'black', name = 'Series 2', tooltip = list(valueDecimals = 0, valueSuffix = '%')) %>%

            #Chart 3
            hc_add_series(x31,  yAxis = 6, color = 'blue',  name = 'Series 31', tooltip = list(valueDecimals = 2)) %>%
            hc_add_series(x32,  yAxis = 6, color = 'green', name = 'Series 32', tooltip = list(valueDecimals = 2)) %>%

            #Chart 'titles'
            hc_annotations(list(labels = list(  list(point = list(x = 0, y = 20),                       text = 'Chart 1',   backgroundColor = 'white', borderColor = 'white', color = 'black', style = list(fontWeight = 'bold')), 
                                                list(point = list(yAxis = 3, x = index(x)[1], y = 90),  text = 'Chart 2',   backgroundColor = 'white', borderColor = 'white', color = 'black', style = list(fontWeight = 'bold')), 
                                                list(point = list(yAxis = 7, x = index(x)[1], y = 0.9), text = 'Chart 3',   backgroundColor = 'white', borderColor = 'white', color = 'black', style = list(fontWeight = 'bold')))))

print(hc)

在上面的例子中,理想情况下,人们可以在图表 1 和图表 3 上有多个系列的地方放置单独的图例。

最简单的解决方案是将legend.layout设置为proximate,看例子:

library(highcharter)
library(gplots)
library(xts)

dates   <- seq(as.Date('2015-04-24'),as.Date('2020-04-24'),1)
nDates  <- NROW(dates)
x11     <- xts(100 * cumprod(1 + 0.0010 * (1 + 0.0002 * rnorm(nDates))), dates)
x12     <- xts(100 * cumprod(1 + 0.0012 * (1 + 0.0001 * rnorm(nDates))), dates)
x2      <- xts(100 * runif(nDates), dates)
x31     <- xts(-1 + 2 * runif(nDates), dates)
x32     <- xts( 1 - 2 * runif(nDates), dates)

glc     <- col2hex('gray65') #gridLineColor)

hc <- highchart(type = 'stock') %>% 
  hc_chart(marginLeft = 150, marginRight = 75) %>% 
  hc_title(text = 'Example', align = 'center', verticalAlign = 'top', style = list(fontWeight = 'bold', fontSize = '20px')) %>%
  hc_rangeSelector(selected = 7) %>%
  hc_navigator(series = list(color = hex_to_rgba('black',1)), top = 580) %>%
  hc_xAxis(type = 'datetime') %>% 
  hc_legend(enabled = TRUE, layout = 'proximate', align = 'left', floating = FALSE) %>%
  hc_yAxis_multiples( 
    #yAxis = 0, plot x11 and x12 here
    list(top = "0%",  height = '60%', opposite = FALSE, type = 'logarithmic', showLastLabel = TRUE, allowDecimals = FALSE, 
         labels = list(align = 'right', x = -10, format = '{value}%', distance = 0), gridLineDashStyle = 'Dot', gridLineColor = glc, startOnTick = FALSE, endOnTick = TRUE),

    #yAxis = 1 to duplicate axis labels on opposite side    
    list(top = "0%",  height = '60%', opposite = TRUE, type = 'logarithmic', showLastLabel = TRUE, allowDecimals = FALSE, linkedTo = 0, opposite = TRUE, 
         labels = list(align = 'right', x =  50, format = '{value}%', distance = 0), gridLineDashStyle = 'Dot', gridLineColor = glc, startOnTick = FALSE, endOnTick = TRUE),

    #yAxis = 2, just to separate the charts
    list(top = '60%', height = '5%'),

    #yAxis = 3, plot x2 here
    list(top = '65%', height = '15%', opposite = FALSE, tickPositions = c(0, 33, 67, 100), gridLineDashStyle = 'Dot', gridLineColor = glc, showLastLabel = TRUE,
         labels = list(align = 'right', x= 35, format = '{value}%', distance = 0)),

    #yAxis = 4, to duplicate the axis labels on the opposite side
    list(top = '65%', height = '15%', linkedTo = 3, opposite = TRUE, tickPositions = c(0, 33, 67, 100), gridLineDashStyle = 'Dot', gridLineColor = glc, showLastLabel = TRUE,
         labels = list(align = 'right', x= 50, format = '{value}%', distance = 0)),

    #yAxis = 5, to separate the charts
    list(top = '80%', height = '5%'),

    #yAxis = 6, plot x31, x32, x33 here
    list(top = '85%', height = '15%', opposite = FALSE, tickPositions = c(-2, -1, 0, 1, 2), gridLineDashStyle = 'Dot', gridLineColor = glc, showLastLabel = TRUE,
         labels = list(align = 'right', x = 30, distance = 0, format = '{value:.1f}'), plotLines = list(list(color = "black", width = 2, value = 0))),

    #yAxis = 7, to duplicate the axis labels on the opposite side
    list(top = '85%', height = '15%', linkedTo = 6, opposite = TRUE, tickPositions = c(-2, -1, 0, 1, 2), gridLineDashStyle = 'Dot', gridLineColor = glc, showLastLabel = TRUE,
         labels = list(align = 'right', x = 50, distance = 0, format = '{value:.1f}'))

  ) %>%


  #Chart 1
  hc_add_series(x11, yAxis = 0, color = 'navy',   name = 'Series 11', tooltip = list(valueDecimals = 1, valueSuffix = '%')) %>%  
  hc_add_series(x12, yAxis = 0, color = 'green',  name = 'Series 12', tooltip = list(valueDecimals = 1, valueSuffix = '%')) %>% 

  #Chart 2
  hc_add_series(x2, yAxis = 3, color = 'black', name = 'Series 2', tooltip = list(valueDecimals = 0, valueSuffix = '%')) %>%

  #Chart 3
  hc_add_series(x31,  yAxis = 6, color = 'blue',  name = 'Series 31', tooltip = list(valueDecimals = 2)) %>%
  hc_add_series(x32,  yAxis = 6, color = 'green', name = 'Series 32', tooltip = list(valueDecimals = 2))


print(hc)

不幸的是,Highstock 中的这种布局存在错误。导航器放置不正确 - 我在这里报告了这个错误:https://github.com/highcharts/highcharts/issues/13392

作为解决方法,我建议使用 navigator.top 属性 移动导航器,但这不是完美的解决方案。我们可以更改核心代码并编写正确自动放置导航器的逻辑,但它需要一些自定义 JavaScript 编码。

如果此解决方案不能满足您的要求,您始终可以使用 Highcharts SVG 渲染器工具渲染您的图例项目,但它也需要一些自定义编码。你可以在Highcharts官方论坛、Whosebug上找到很多自定义图例的例子,或者你可以看我写的这篇关于Renderer用法的文章:https://support.highcharts.com/support/solutions/articles/44001706971-how-to-use-highcharts-svg-renderer