Vlad
Vlad

Reputation: 3764

plotly R: bar chart with two axes

Is it possible to have two axes for a bar chart using plotly for R?

The code is modified from plotly bar chart example

library(plotly)

x <- c('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')
y1 <- c(20, 14, 25, 16, 18, 22, 19, 15, 12, 16, 14, 17)/10
y2 <- c(19, 14, 22, 14, 16, 19, 15, 14, 10, 12, 12, 16)
data <- data.frame(x, y1, y2)

#The default order will be alphabetized unless specified as below:
data$x <- factor(data$x, levels = data[["x"]])

p <- plot_ly(data, x = ~x, y = ~y1, type = 'bar', name = 'Primary Product', marker = list(color = 'rgb(49,130,189)')) %>%
  add_trace(y = ~y2, name = 'Secondary Product', marker = list(color = 'rgb(204,204,204)')) %>%
  layout(xaxis = list(title = "", tickangle = -45),
         yaxis = list(title = ""),
         margin = list(b = 100),
         barmode = 'group')
p

This gives:

bar plot 1

Values for the primary product are much smaller than secondary product - my purpose is to compare proportions by month, while still having y-axes show the actual values rather than a normalised value so it looks like this (mocked up):

enter image description here

I have tried plotly help to add another axis, here's the code. However, it doesn't seem to do anything, the resulting chart is the same as first one.

library(plotly)

x <- c('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')
y_1 <- c(20, 14, 25, 16, 18, 22, 19, 15, 12, 16, 14, 17)/10
y_2 <- c(19, 14, 22, 14, 16, 19, 15, 14, 10, 12, 12, 16)
data <- data.frame(x, y_1, y_2)

#The default order will be alphabetized unless specified as below:
data$x <- factor(data$x, levels = data[["x"]])

ay <- list(
  tickfont = list(color = "red"),
  overlaying = "y",
  side = "right",
  title = "second y axis"
)
p <- plot_ly(data, x = ~x, y = ~y_1, type = 'bar', name = 'Primary Product', marker = list(color = 'rgb(49,130,189)')) %>%
  add_trace(y = ~y_2, name = 'Secondary Product', marker = list(color = 'rgb(204,204,204)'), axis = "y2") %>%
  layout(yaxis2 = ay,
         xaxis = list(title = "", tickangle = -45),
         yaxis = list(title = ""),
         margin = list(b = 100),
         barmode = 'group')
p

Update 9 Aug 2018

MLavoie posted this code, which is similar to the attempt, however it gives a stacked bar chart - which is not the intended result.

data$x <- factor(data$x, levels = data[["x"]])

ay <- list(
  tickfont = list(color = "red"),
  overlaying = "y",
  side = "right",
  title = "second y axis"
)

p <- plot_ly() %>% 
add_bars(data, x = ~x, y = ~y1, name = 'Primary Product', marker = list(color = 'rgb(49,130,189)')) %>%
add_bars(data, x = ~x, y = ~y2, name = 'Secondary Product', marker = list(color = 'rgb(204,204,204)'), yaxis = "y2") %>%
layout(yaxis2 = ay,
       xaxis = list(title = "", tickangle = -45),
       yaxis = list(title = ""),
       margin = list(b = 100),
       barmode = 'group')
p  

enter image description here

Upvotes: 4

Views: 5473

Answers (4)

Martin
Martin

Reputation: 441

I played with this answer and found the following derivative to give the best result.

This is the resulting plot:

https://i.sstatic.net/CLRNe.png

library(plotly)
library(dplyr)

x <- c('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')
y1 <- c(20, 14, 25, 16, 18, 22, 19, 15, 12, 16, 14, 17)/10
y2 <- c(19, 14, 22, 14, 16, 19, 15, 14, 10, 12, 12, 16)
data <- data.frame(x, y1, y2)

data$x <- factor(data$x, levels = data[["x"]])

ay <- list(
  overlaying = "y",
  side = "right",
  title = "Right Hand Axis"
)

p <- plot_ly() %>% 
  add_bars(data, x = ~x, y = ~y1, name = 'Primary Product (LHS)', 
           marker = list(color = 'rgb(49,130,189)'), offsetgroup = 1) %>%
  add_bars(data, x = ~x, y = ~y2, name = 'Secondary Product (RHS)', 
           marker = list(color = 'rgb(204,204,204)'), yaxis = "y2", offsetgroup = 2) %>%
  layout(yaxis2 = ay,
         xaxis = list(title = "Time Period", tickangle = -45),
         yaxis = list(title = "Left Hand Axis"),
         margin = list(b = 100),
         barmode = 'group',
         legend = list(x = 1.1, y = 1))

p  

Upvotes: 5

Morinaga
Morinaga

Reputation: 35

According to the discussion here, this should work.

x <- c('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')
y1 <- c(20, 14, 25, 16, 18, 22, 19, 15, 12, 16, 14, 17)/10
y2 <- c(19, 14, 22, 14, 16, 19, 15, 14, 10, 12, 12, 16)
data <- data.frame(x, y1, y2)

data$x <- factor(data$x, levels = data[["x"]])

ay <- list(
  tickfont = list(color = "red"),
  overlaying = "y",
  side = "right",
  title = "second y axis"
)

p <- plot_ly() %>% 
  add_bars(data, x = ~x, y = ~y1, name = 'Primary Product', 
           marker = list(color = 'rgb(49,130,189)'), offsetgroup = 1) %>%
  add_bars(data, x = ~x, y = ~y2, name = 'Secondary Product', 
           marker = list(color = 'rgb(204,204,204)'), yaxis = "y2", offsetgroup = 2) %>%
  layout(yaxis2 = ay,
         xaxis = list(title = "", tickangle = -45),
         yaxis = list(title = ""),
         margin = list(b = 100),
         barmode = 'group')
p  

The attribute offsetgroup allows you to have more control over how the cross-trace offset and width values are computed.

Resulting plot

Upvotes: 0

augustin-barillec
augustin-barillec

Reputation: 531

A solution is to create two extra traces. Here is an example in Python :

enter image description here

This code is based on the code of the following separate question : Plotly Python: Align X-Axes in a grouped bar chart with multiple Y-axis

Upvotes: 0

MLavoie
MLavoie

Reputation: 9836

I think you have a few typos, but this work.

data$x <- factor(data$x, levels = data[["x"]])

ay <- list(
  tickfont = list(color = "red"),
  overlaying = "y",
  side = "right",
  title = "second y axis"
)

p <- plot_ly() %>% 
add_bars(data, x = ~x, y = ~y1, name = 'Primary Product', marker = list(color = 'rgb(49,130,189)')) %>%
add_bars(data, x = ~x, y = ~y2, name = 'Secondary Product', marker = list(color = 'rgb(204,204,204)'), yaxis = "y2") %>%
layout(yaxis2 = ay,
       xaxis = list(title = "", tickangle = -45),
       yaxis = list(title = ""),
       margin = list(b = 100),
       barmode = 'group')
p

Upvotes: 0

Related Questions