R Highcharter:用同步缩放/工具提示分隔图例或多个图表的巧妙方法?
Posted
技术标签:
【中文标题】R Highcharter:用同步缩放/工具提示分隔图例或多个图表的巧妙方法?【英文标题】:R Highcharter: Clever way to separate legends or multiple charts with synchronized zoom/tooltip? 【发布时间】:2020-08-10 07:49:36 【问题描述】:我的问题与我使用 highstock 绘制多个堆叠 y 轴的情况有关,例如这里的最后一个示例:http://jkunst.com/highcharter/highstock.html。
我希望每个 y 轴都有单独的图例,但进行一些挖掘似乎 highcharts 只能有一个图例 (Highcharts multiple legends)。
然后我想也许我可以使用注释来模仿所需的图例。但是绘制彩色线段会很混乱,因为它们会显示为系列(尽管我想我可以只使用彩色文本来指示哪个系列是哪个系列)。
在 highcharts 中使用多个 y 轴时,是否有一种巧妙的方法来解决单一图例的限制?
如果不是,那么如果我绝对需要有单独的图例,我似乎不得不使用多个堆叠图表。在这种情况下,我需要在这些多个图表中同步缩放和工具提示。有很多关于如何通过 javascript 执行此操作的信息(我的经验有限),但似乎也经常出现让缩放和工具提示同步的问题。
我想知道是否有任何关于如何在 R highcharter 中跨多个图表同步缩放和工具提示的示例(我已经搜索过高和低但无法找到)?
我非常感谢这里的社区可能提供的任何见解。
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 上放置单独的图例。
【问题讨论】:
嗨!如果我必须选择是尝试创建自定义图例还是同步图表 - 我会采用自定义图例方式。目前(我们正在 Highcharts 中制作多个图例,我希望我们能尽快完成,它将成为下一个版本的一部分)但现在,理论上,你只能拥有一个图例。但没有什么能阻止您创建自定义图例。如果您向我提供它应该是什么样子的模型(可在 RStudio 中重现的示例 Highcharter 演示也会很有帮助),那么我将帮助您实现它,或者至少建议您具体可以做什么。 @raf18seb 我非常感谢您的洞察力。令人鼓舞的是,未来可能会有解决方案。谢谢你。我编辑了帖子以显示一些示例代码,这些代码基本上是我正在寻找的所有内容(目前)减去一些将单独的图例放在具有多个系列的图表上的方法(在上面的示例中,图表 1 和3,分别位于 y 轴 0 和 6)。 【参考方案1】:最简单的解决方案是将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 Renderer 工具渲染您的图例项目,但它也需要一些自定义编码。您可以在 Highcharts 官方论坛 *** 上找到许多自定义图例的示例,或者您可以查看我写的有关 Renderer 使用的这篇文章:https://support.highcharts.com/support/solutions/articles/44001706971-how-to-use-highcharts-svg-renderer
【讨论】:
非常感谢您提供的信息,它非常有用。对于这个特定的示例,legend.layout proximate 的使用对我来说不太适用,但是您已经为我指明了正确的道路,并提醒我在未来的 highcharts 版本中可能有多个图例的解决方案。非常感谢。 这是带有此增强功能的票证:github.com/highcharts/highcharts/issues/11309,这是 PR github.com/highcharts/highcharts/pull/12478,但尚未被接受并合并到 Highcharts 核心中 关于 PR 是否或何时被接受和合并有任何想法吗? 很遗憾没有。据我所知,这个模块存在一些兼容性问题,它正在等待一些最终决定。您可以直接在 GitHub 票证中提出这个问题,您将直接从从事此模块的核心开发人员那里得到答案。 @KamilKulig 你有更多信息吗?以上是关于R Highcharter:用同步缩放/工具提示分隔图例或多个图表的巧妙方法?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 R 中将 Highcharter 图表保存为 gif?
深入研究来自不同组的多个系列 - Highcharter(R 中)