一条零线对应两个y轴

时间:2018-09-21 12:21:46

标签: r plotly

enter image description here

此图是使用以下代码生成的:

library(tidyverse)
library(plotly)

df <- data.frame(
      DEP = c("ABC", "DEF", "GHI")
      , VALUE = c(100, 110, 120)
      , LINE = c(-0.1, 0.7, 0.9)
    )

xAxis <- list(
  title = ""
  , tickangle = 0
  , tickfont = list(size = 10)
)

yAxis <- list(
  side = "left"
  , showgrid = TRUE
  , zeroline = TRUE
  , title = ""
)

yAxis2 <- list(
  side = "right"
  , autotick = FALSE
  , ticks = "outside"
  , tick0 = 0
  , dtick = 0.1
  , showgrid = TRUE
  , zeroline = TRUE
  , overlaying = "y"
)

plot_ly(data = df, x = ~DEP) %>%
  add_trace(data = df, x = ~DEP, y = ~VALUE, name = 'VALUE', type = "bar", yaxis = "y", textposition = "auto") %>%
  add_trace(data = df, x = ~DEP, y = ~LINE, name = 'LINE', mode = "lines", type = "scatter",
            line = list(width = 4), yaxis = "y2") %>%
  layout(
    margin = list(r=50, b = 150)
    , xaxis = xAxis
    , yaxis = yAxis
    , yaxis2 = yAxis2
    , showlegend = FALSE
  )
  

我想更改图形,以使左侧y的零线   轴移到右y轴的零线。因此   小节也应该移动:

enter image description here

1 个答案:

答案 0 :(得分:1)

据我所知,无法在Plotly中直接进行操作。但是您可以手动设置两个轴的range

对于您的条形图,在其布局中添加以下行:

range = c(max(df$VALUE) / max(df$LINE) * min(df$LINE), max(df$VALUE))

和您的台词:

range = c(min(df$LINE), max(df$LINE))

这将给出以下图形。 enter image description here

一种更简单的方法是将下限设置为0,从而将折线图截断。

在下面的代码中,添加了一个附加变量axis_buffer,以避免该范围恰好是您的值的上下限。

为了清晰起见,我将删除一些网格线或尝试对数据进行规范化并将原始数据添加到悬停信息中。

library('plotly')
df <- data.frame(
  DEP = c("ABC", "DEF", "GHI")
  , VALUE = c(100, 110, 120)
  , LINE = c(-0.1, 0.7, 0.9)
)

axis_buffer <- 1.1

xAxis <- list(
  title = ""
  , tickangle = 0
  , tickfont = list(size = 10)
)

yAxis <- list(
  side = "left"
  , showgrid = TRUE
  , zeroline = TRUE
  , title = ""
  , range = c(max(df$VALUE) / max(df$LINE) * min(df$LINE) * axis_buffer, max(df$VALUE) * axis_buffer)
)

yAxis2 <- list(
  side = "right"
  , autotick = FALSE
  , ticks = "outside"
  , tick0 = 0
  , dtick = 0.1
  , showgrid = TRUE
  , zeroline = TRUE
  , overlaying = "y"
  , range = c(min(df$LINE) * axis_buffer, max(df$LINE) * axis_buffer)
)

plot_ly(data = df, x = ~DEP) %>%
  add_trace(data = df, x = ~DEP, y = ~VALUE, name = 'VALUE', type = "bar", yaxis = "y", textposition = "auto") %>%
  add_trace(data = df, x = ~DEP, y = ~LINE, name = 'LINE', mode = "lines", type = "scatter",
            line = list(width = 4), yaxis = "y2") %>%
  layout(
    margin = list(r=50, b = 150)
    , xaxis = xAxis
    , yaxis = yAxis
    , yaxis2 = yAxis2
    , showlegend = FALSE
  )