【问题标题】:How to have 2 traces on y1 & y2 axis with highlight function in Plotly如何在 Plotly 中使用高亮功能在 y1 和 y2 轴上有 2 条轨迹
【发布时间】:2026-01-20 20:50:01
【问题描述】:

我需要绘制 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))

【问题讨论】:

    标签: r plotly r-plotly


    【解决方案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 我添加了一个关于跟踪索引的更复杂的示例。