如何在 Plotly 中使用高亮功能在 y1 和 y2 轴上有 2 条轨迹

Posted

技术标签:

【中文标题】如何在 Plotly 中使用高亮功能在 y1 和 y2 轴上有 2 条轨迹【英文标题】:How to have 2 traces on y1 & y2 axis with highlight function in Plotly 【发布时间】:2021-12-21 07:59:33 【问题描述】:

我需要绘制 2 条轨迹,一条在左侧 y 轴,一条在右侧,我想保留高亮功能。因此,data 参数对于两个跟踪是不同的。

有没有办法做到这一点?

library(plotly)

## Data ################
tmp <- data.frame(timestamp = structure(c(1632132000, 1632139200, 1632146400, 1632153600, 1632160800, 1632168000, 
                                          1632175200, 1632182400, 1632189600, 1632196800, 1632204000, 1632211200, 
                                          1632132000, 1632139200, 1632146400, 1632153600, 1632160800, 1632168000,
                                          1632175200, 1632182400, 1632189600, 1632196800, 1632204000, 1632211200), 
                                        class = c("POSIXct", "POSIXt"), tzone = "Europe/Berlin"), 
                  value = c(29.015, 25.724, 24.017, 25.118, 28.334, 30.408, 
                            32.046, 32.441, 29.463, 27.528, 24.136, 21.067, 27.352, 23.13, 
                            24.962, 24.558, 130.475, 148.465, 157.134, 149.983, 133.003, 
                            123.9, 117.334, 115.927), 
                  valuetype = c(rep("Type 1",12),rep("Type 2",12)),
                  route_name = rep("group 1", 24), 
                  value_color = c(rep("#e3a201", 12), rep("#FFBA00",12)))

## Plotly ###############
plot_ly(data = tmp) %>%
  highlight_key(~paste0(route_name, valuetype)) %>%
  ## 1 Trace ###################
  add_trace(
    data = tmp[tmp$valuetype %in% unique(tmp$valuetype)[[1]],],
    inherit = FALSE,
            x = ~timestamp, y = ~value,
            type = "scattergl", mode = "lines",
            name = ~paste(valuetype, route_name),
            color = ~I(value_color)) %>%
  ## 2 Trace ###################
  add_trace(
    data = tmp[tmp$valuetype %in% unique(tmp$valuetype)[[2]],],
    inherit = FALSE,
            x = ~timestamp, y = ~value,
            yaxis = "y2",
            type = "scattergl", mode = "lines",
            name = ~paste(valuetype, route_name),
            color = ~I(value_color)) %>%
  ## Layout for Group 1&2 ###################
  plotly::layout(xaxis = list(title = "Zeit", type = "date"),
                 yaxis = list(side ="left", title = "Y-Title"),
                 yaxis2 = list(side="right", overlaying = "y", title = "Y2-Title"),
                 margin = list(l=50,r=50,t=50,b=10),
                 legend = list(orientation = 'h', xanchor = 'center', x = 0.5, y = -0.2)) %>% 
    plotly::highlight(on = "plotly_hover", off = "plotly_doubleclick",
                      selected = attrs_selected(showlegend = FALSE))

【问题讨论】:

【参考方案1】:

不确定这是否适合您,但如果您只使用单个 data 参数,您可以使用 style 将轨迹分配给另一个 y 轴:

library(plotly)

## Data ################
tmp <- data.frame(timestamp = structure(c(1632132000, 1632139200, 1632146400, 1632153600, 1632160800, 1632168000, 
                                          1632175200, 1632182400, 1632189600, 1632196800, 1632204000, 1632211200, 
                                          1632132000, 1632139200, 1632146400, 1632153600, 1632160800, 1632168000,
                                          1632175200, 1632182400, 1632189600, 1632196800, 1632204000, 1632211200), 
                                        class = c("POSIXct", "POSIXt"), tzone = "Europe/Berlin"), 
                  value = c(29.015, 25.724, 24.017, 25.118, 28.334, 30.408, 
                            32.046, 32.441, 29.463, 27.528, 24.136, 21.067, 27.352, 23.13, 
                            24.962, 24.558, 130.475, 148.465, 157.134, 149.983, 133.003, 
                            123.9, 117.334, 115.927), 
                  valuetype = c(rep("Type 1",12),rep("Type 2",12)),
                  route_name = rep("group 1", 24), 
                  value_color = c(rep("#e3a201", 12), rep("#FFBA00",12)))

## Plotly ###############
tmp %>% highlight_key(~paste0(route_name, valuetype)) %>%
plot_ly(
  x = ~timestamp, y = ~value,
  type = "scatter", mode = "lines", # "scattergl"
  name = ~paste(valuetype, route_name),
  color = ~I(value_color)) %>%
  ## assign trace 1 to y2
  style(yaxis = "y2", traces = 1) %>%
  ## Layout for Group 1&2 ###################
plotly::layout(xaxis = list(title = "Zeit", type = "date"),
               yaxis = list(side ="left", title = "Y-Title"),
               yaxis2 = list(side="right", overlaying = "y", title = "Y2-Title"),
               margin = list(l=50,r=50,t=50,b=10),
               legend = list(orientation = 'h', xanchor = 'center', x = 0.5, y = -0.2)) %>% 
  plotly::highlight(on = "plotly_hover", off = "plotly_doubleclick", selected = attrs_selected(showlegend = FALSE))


编辑:跟踪索引示例:

library(plotly)
library(data.table)

## Data ################
tmp <- data.frame(timestamp = structure(c(1632132000, 1632139200, 1632146400, 1632153600, 1632160800, 1632168000, 
                                          1632175200, 1632182400, 1632189600, 1632196800, 1632204000, 1632211200, 
                                          1632132000, 1632139200, 1632146400, 1632153600, 1632160800, 1632168000,
                                          1632175200, 1632182400, 1632189600, 1632196800, 1632204000, 1632211200,
                                          1632132000, 1632139200, 1632146400, 1632153600, 1632160800, 1632168000, 
                                          1632175200, 1632182400, 1632189600, 1632196800, 1632204000, 1632211200, 
                                          1632132000, 1632139200, 1632146400, 1632153600, 1632160800, 1632168000,
                                          1632175200, 1632182400, 1632189600, 1632196800, 1632204000, 1632211200), 
                                        class = c("POSIXct", "POSIXt"), tzone = "Europe/Berlin"), 
                  value = c(c(29.015, 25.724, 24.017, 25.118, 28.334, 30.408, 
                            32.046, 32.441, 29.463, 27.528, 24.136, 21.067, 27.352, 23.13, 
                            24.962, 24.558, 130.475, 148.465, 157.134, 149.983, 133.003, 
                            123.9, 117.334, 115.927), c(29.015, 25.724, 24.017, 25.118, 28.334, 30.408, 
                                                        32.046, 3.441, 2.463, 2.528, 2.136, 2.067, 2.352, 23.13, 
                                                        24.962, 24.558, 13.475, 14.465, 15.134, 14.983, 13.003, 
                                                        123.9, 117.334, 115.927) + 50), 
                  valuetype = c(rep("Type 1",12), rep("Type 2", 12), rep("Type 3", 12), rep("Type 4", 12)),
                  route_name = rep("group 1", 48), 
                  value_color = c(rep("#e3a201", 12), rep("#FFBA00", 12), rep("red", 12), rep("darkgreen", 12)),
                  yaxis = c(rep("y", 12), rep("y2", 12), rep("y", 12), rep("y3", 12)))

setDT(tmp)
tmp[, trace_index := .GRP-1, by = .(route_name, valuetype)]

## Plotly ###############
shared_data <- highlight_key(tmp, ~paste0(route_name, valuetype))

fig <- plot_ly(data = shared_data,
               x = ~timestamp, y = ~value,
               type = "scatter", mode = "lines", # "scattergl"
               name = ~paste(valuetype, route_name),
               color = ~I(value_color))

if(any(tmp$yaxis != "y"))
  axesMapping <- unique(tmp[yaxis != "y", c("yaxis","trace_index")])
  
  # layout call to add the axis could be added here
  for(i in seq_len(NROW(axesMapping)))
    fig <- do.call(plotly::style, list(p = fig, yaxis = axesMapping[i,]$yaxis, traces = axesMapping[i,]$trace_index))
  


## Layout for Group 1&2 ###################
plotly::layout(fig,
               xaxis = list(title = "Zeit", type = "date", domain = c(0, 0.75)),
               yaxis = list(side ="left", title = "Y-Title"),
               yaxis2 = list(side="right", overlaying = "y", title = "Y2-Title"),
               yaxis3 = list(side="right", overlaying = "y", anchor="free", position = 0.85, title = "Y3-Title"),
               margin = list(l=50,r=50,t=50,b=10),
               legend = list(orientation = 'h', xanchor = 'center', x = 0.5, y = -0.2)) %>% 
  plotly::highlight(on = "plotly_hover", off = "plotly_doubleclick", selected = attrs_selected(showlegend = FALSE))

【讨论】:

这是个好主意,但我不确定我是否可以使用它,因为绘图可以有多个轨迹,有时带有第二个 y 轴,有时没有.. 我不知道我是否可以预先知道 y2 的跟踪指数。 跟踪索引的顺序应该与你的数据顺序相对应——所以应该可以。但是,different trace types 有一个限制。 @SeGa 我添加了一个关于跟踪索引的更复杂的示例。

以上是关于如何在 Plotly 中使用高亮功能在 y1 和 y2 轴上有 2 条轨迹的主要内容,如果未能解决你的问题,请参考以下文章

Plotly:如何在 Plotly 中绘制具有渐变颜色的矩形?

在 Plotly 中使用循环制作形状

如何在 Zeppelin 中使用 Plotly

Plotly:如何使用类似于在图例中单击它们的按钮来切换轨迹?

使用 Plotly.js 自定义垂直线

如何使用 Plotly 在 Python 中使用 Pandas 数据框列设置散点图悬停信息