I want to set a minimum value on the secondary y-axis. This is my code :
library(plotly)
# my data
value <- c(300000,400000,500000,600000,500000,600000)
x1 <- c(3,4,5,5,4,3)
x2 <-c(3,4,5,5,4,3)
name <- c("martin","john","marc","igor","thea","julia")
df <- data.frame(value, x1, x2, name)
# graph with plotly
graph=df %>%
plot_ly(x = ~name) %>%
add_bars(y = ~x1,
name = "bar1") %>%
add_bars(y = ~x2,
name = "bar2") %>%
add_lines(y = ~value,
name = "line",
yaxis = "y2") %>%
layout(barmode = "bar",
yaxis2 = list(overlaying = "y",
side = "right"),
barmode = "bar",
legend = list(x = 1.1, y =1))
# showing graph
graph
and i get this :
but i want the secondary y-axis start at 200k (or 100k) instead of 300k.
How can we fix it ? Some help would be appreciated
Generally, if you've already got a fig set up:
fig <- fig %>% layout(yaxis2 = list(range = c(<min>, <max>)))
And in your specific case:
graph <- graph %>% layout(yaxis2 = list(range = c(200000,600000)))
Plot
Complete code:
library(plotly)
# my data
value <- c(300000,400000,500000,600000,500000,600000)
x1 <- c(3,4,5,5,4,3)
x2 <-c(3,4,5,5,4,3)
name <- c("martin","john","marc","igor","thea","julia")
df <- data.frame(value, x1, x2, name)
# graph with plotly
graph=df %>%
plot_ly(x = ~name) %>%
add_bars(y = ~x1,
name = "bar1") %>%
add_bars(y = ~x2,
name = "bar2") %>%
add_lines(y = ~value,
name = "line",
yaxis = "y2") %>%
layout(barmode = "bar",
yaxis2 = list(overlaying = "y",
side = "right"),
barmode = "bar",
legend = list(x = 1.1, y =1))
# showing graph
#graph
graph <- graph %>% layout(yaxis2 = list(
#scaleanchor = "x",
#scaleratio = 0.2,
range = c(200000,600000)
#title = "1:5"
))
graph
Related
I am trying to draw a subplot that contains 2 plots. Each inner plots have two y-axis and two x-axis. I also want to match each y label with his lines color.
First I want to start with a simple example. Consider following code
library(plotly)
library(dplyr)
p1 <- economics %>% plot_ly()%>%
add_trace( x = ~date, y = ~unemploy,yaxis='y1',type='scatter',mode="lines+markers")%>%
add_trace(x = ~date, y = ~uempmed,yaxis='y2',type='scatter',mode="lines+markers") %>%
layout( yaxis2 = list(overlaying = "y1",side = "right"))
p2<-p1
>p1
The output:
subplot(p1, p2 , nrows = 2 , shareX = TRUE)
The output:
So the subplot does not work fine. How to fix it?
EDIT:
With a little change to the code as shown below and it work!
R code
library(plotly)
library(dplyr)
p1 <- economics %>% plot_ly()%>%
add_trace( x = ~date, y =~unemploy,yaxis='y',type='scatter',mode="lines+markers")%>%
add_trace(x = ~date, y = ~uempmed,yaxis='y2',type='scatter',mode="lines+markers") %>%
layout( yaxis = list(side = "left"),yaxis2 = list(overlaying = "y",side = "right"))
p2<-economics %>% plot_ly()%>%
add_trace( x = ~date, y = ~unemploy,yaxis='y',type='scatter',mode="lines+markers")%>%
add_trace(x = ~date, y = ~uempmed,yaxis='y2',type='scatter',mode="lines+markers") %>%
layout(yaxis = list(side = "left"), yaxis2 = list(overlaying = "y3",side = "right"))
subplot(p1,p2,nrows=2)
The output now is as follows:
To extend for have 3 plots:
library(plotly)
library(dplyr)
p1 <- economics %>% plot_ly()%>%
add_trace( x = ~date, y = ~unemploy,yaxis='y',type='scatter',mode="lines+markers")%>%
add_trace(x = ~date, y = ~uempmed,yaxis='y2',type='scatter',mode="lines+markers") %>%
layout( yaxis = list(side = "left"),yaxis2 = list(overlaying = "y",side = "right"))
p2<-economics %>% plot_ly()%>%
add_trace( x = ~date, y = ~unemploy,yaxis='y',type='scatter',mode="lines+markers")%>%
add_trace(x = ~date, y = ~uempmed,yaxis='y2',type='scatter',mode="lines+markers") %>%
layout(yaxis = list(side = "left"), yaxis2 = list(overlaying = "y3",side = "right"))
p3<-economics %>% plot_ly()%>%
add_trace( x = ~date, y = ~unemploy,yaxis='y',type='scatter',mode="lines+markers")%>%
add_trace(x = ~date, y = ~uempmed,yaxis='y2',type='scatter',mode="lines+markers") %>%
layout(yaxis = list(side = "left"), yaxis2 = list(overlaying = "y5",side = "right"))
subplot(p1,p2,p3,nrows=3)
The output:
I am using the R programming language. I am following this tutorial over here: https://plotly.com/r/dropdowns/
I tried to create my own data and run the same procedure:
library(plotly)
library(MASS)
library(dplyr)
# create data
x <- sample( LETTERS[1:4], 731, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25) )
y <- rnorm(731,10,10)
z <- rnorm(731,5,5)
date= seq(as.Date("2014/1/1"), as.Date("2016/1/1"),by="day")
df <- data.frame(x,y, z, date)
df$x = as.factor(df$x)
#create plot
fig <- plot_ly(df, x = ~y, z = ~z )
fig <- fig %>% plot_ly(df, y = ~y, color = ~x, type = "box")
fig <- fig %>% plot_ly( data = df, type = "scatter", mode = "markers", x = ~ y, y = ~z)
fig <- fig %>% layout(
title = "Drop down menus - Styling",
xaxis = list(domain = c(0.1, 1)),
yaxis = list(title = "y"),
updatemenus = list(
list(
y = 0.8,
buttons = list(
list(method = "restyle",
args = list("line.color", "blue"),
label = "Blue"),
list(method = "restyle",
args = list("line.color", "red"),
label = "Red")))
)
)
fig
But this produces the following error:
Error: First argument, `data`, must be a data frame or shared data.
I tried to add another plot to this "fig"
# time series plot
aggregate = df %>%
mutate(date = as.Date(date)) %>%
group_by(month = format(date, "%Y-%m")) %>%
summarise( mean = mean(y))
ts_1 <- ggplot(aggregate) + geom_line(aes(x = month, y = mean, group = 1)) + theme(axis.text.x = element_text(angle = 90)) + ggtitle("time series 1")
plot_1 = ggplotly(ts_1)
fig <- fig %>% plot_1
But this also does not work.
Can someone please show me what I am doing wrong?
Thanks
I am not sure which plot from that page you are trying to implement. Here is a way to implement first 2 of them.
Data :
library(plotly)
x <- sample( LETTERS[1:4], 731, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25) )
y <- rnorm(731,10,10)
z <- rnorm(731,5,5)
date= seq(as.Date("2014/1/1"), as.Date("2016/1/1"),by="day")
df <- data.frame(x,y, z, date)
df$x = as.factor(df$x)
Simple Dropdown :
fig <- plot_ly(df, x = ~y, y = ~z)
fig <- fig %>% add_markers(marker = list(line = list(color = "black", width = 1)))
fig <- fig %>% layout(
title = "Drop down menus - Plot type",
xaxis = list(domain = c(0.1, 1)),
yaxis = list(title = "y"),
updatemenus = list(
list(
y = 0.8,
buttons = list(
list(method = "restyle",
args = list("type", "scatter"),
label = "Scatter"),
list(method = "restyle",
args = list("type", "histogram2d"),
label = "2D Histogram")))
))
fig
For the 2nd plot :
fig <- plot_ly(df, x = ~date)
fig <- fig %>% add_lines(y = ~y, name = "A")
fig <- fig %>% add_lines(y = ~z, name = "B", visible = F)
fig <- fig %>% layout(
title = "Drop down menus - Styling",
xaxis = list(domain = c(0.1, 1)),
yaxis = list(title = "y"),
updatemenus = list(
list(
y = 0.8,
buttons = list(
list(method = "restyle",
args = list("line.color", "blue"),
label = "Blue"),
list(method = "restyle",
args = list("line.color", "red"),
label = "Red")))
)
)
fig
Is there a way to change the order of subplots in plotly for R? Is there a way to manually change the levels of a factor in this code?
I want a plot with Weight in the first plot followed by a,b,c in order above it. But what I get as output is Weight, c, a and b as shown in the image graph
Here is my code
df<-data.frame("time"= seq(0.01,10,length.out=100),"Weight"=1:100, "a"=rnorm(100),"b"=rnorm(100),"c"=rnorm(100))
q <- df%>%
tidyr::gather(variable, value, -time) %>%
transform(id = as.integer(factor(variable))) %>%
plot_ly(x = ~time, y = ~value, color = ~variable, colors = "Dark2",
yaxis = ~paste0("y", id)
) %>%
layout(
xaxis = list(title = "Time,s",tickfont = list(size = 17),titlefont = list(size = 20)),
yaxis = list(tickfont = list(size = 17), title="DP"),
hoverlabel = list(font=list(size=20))
) %>%
add_lines() %>%
subplot(nrows = length(df)-1, shareX = TRUE)
One way to do this is re-ordering factor levels as below:
# set.seed to keep the exact same results
set.seed(123)
df<-data.frame("time"= seq(0.01,10,length.out=100),"Weight"=1:100, "a"=rnorm(100),"b"=rnorm(100),"c"=rnorm(100))
DF <- df%>%
tidyr::gather(variable, value, -time) %>%
transform(id = as.integer(factor(variable)))
DF$variable <- factor(DF$variable, levels = c("Weight", "a", "b", "c")) #re-order
q <- DF %>%
plot_ly(x = ~time, y = ~value, color = ~variable, colors = "Dark2",
yaxis = ~paste0("y", sort(id, decreasing =F))) %>% #sort the order
layout(
xaxis = list(title = "Time,s",tickfont = list(size = 17),titlefont = list(size = 20)),
yaxis = list(tickfont = list(size = 17), title="DP"),
hoverlabel = list(font=list(size=20))
) %>%
add_lines() %>%
subplot(nrows = length(df)-1, shareX = TRUE)
q
You will need sort(id, decreasing =F) to get exact same order of what you set in factor(DF$variable, levels = c("Weight", "a", "b", "c")).
Exchange the data, the name, and the line features of the top and bottom subplots as following code,
#assign q$x$data to one template variable p
p = q$x$data
#exchange the data, name, and line features of q$x$data[[1]] and q$x$data[[4]]
q$x$data[[1]]$x = p[[4]]$x
q$x$data[[1]]$y = p[[4]]$y
q$x$data[[1]]$name = p[[4]]$name
q$x$data[[1]]$line = p[[4]]$line
q$x$data[[4]]$x = p[[1]]$x
q$x$data[[4]]$y = p[[1]]$y
q$x$data[[4]]$name = p[[1]]$name
q$x$data[[4]]$line = p[[1]]$line
#show
q
The problem might have been caused by yaxis = ~paste0("y", id). I replaced it with yaxis = ~paste0(id, "y") to get the correct order. You may need to change some code to get the right format.
library(plotly)
df<-data.frame("time"= seq(0.01,10,length.out=100),"Weight"=1:100, "a"=rnorm(100),"b"=rnorm(100),"c"=rnorm(100))
q <- df%>%
tidyr::gather(variable, value, -time) %>%
transform(id = as.integer(factor(variable))) %>%
plot_ly(x = ~time, y = ~value, color = ~variable, colors = "Dark2",
yaxis = ~paste0(id, "y")
) %>%
layout(
xaxis = list(title = "Time,s",tickfont = list(size = 17),titlefont = list(size = 20)),
yaxis = list(tickfont = list(size = 17), title="DP"),
hoverlabel = list(font=list(size=20))
) %>%
add_lines() %>%
subplot(nrows = length(df), shareX = TRUE)
q
I have the following data:
df <- data.frame(numbers = rep(1:3, 30),
letter = sample(c("A", "B", "C", "D"), 90, replace = TRUE),
status = sample(c("good", "bad", "ugly"), 90, replace = TRUE))
I am trying to replicate this ggplot2 plot, but make it interactive:
ggplot(df, aes(letter, fill = status)) + geom_bar() + facet_wrap(.~numbers)
If I use ggplotly, then I can select and deselect variables, but the bars do not readjust so I get something that looks like this:
So my idea was to cast the data, then create individual plotly plots and use subplot:
df_group <- df %>% group_by(numbers, letter, status) %>% tally()
df_group_cast <- dcast(df_group, numbers + letter ~ status)
p1 <- df_group_cast %>%
filter(numbers == 1) %>%
plot_ly(x = ~letter, y = ~good, type = 'bar', name = 'good') %>%
add_trace(y = ~bad, name = 'bad') %>%
add_trace(y = ~ugly, name = 'ugly') %>%
layout(yaxis = list(title = 'Count'), barmode = 'stack')
p2 <- df_group_cast %>%
filter(numbers == 2) %>%
plot_ly(x = ~letter, y = ~good, type = 'bar', name = 'good') %>%
add_trace(y = ~bad, name = 'bad') %>%
add_trace(y = ~ugly, name = 'ugly') %>%
layout(yaxis = list(title = 'Count'), barmode = 'stack')
p3 <- df_group_cast %>%
filter(numbers == 3) %>%
plot_ly(x = ~letter, y = ~good, type = 'bar', name = 'good') %>%
add_trace(y = ~bad, name = 'bad') %>%
add_trace(y = ~ugly, name = 'ugly') %>%
layout(yaxis = list(title = 'Count'), barmode = 'stack')
subplot(p1, p2, p3)
This is interactive, but also looks bad. I would like them to share a scale, have one legend, and have titles for each number group.
Is this possible?
(I am trying to embed an interactive graph like this into slidify, if there are better libraries I am open to using them. So far rCharts has failed me, so I'm trying plotly)
I figured it out! Didn't need to cast my data in the end. I have even added a step for adding subgroup titles.
df_group <- df %>% group_by(numbers, letter, status) %>% tally()
Put together annotation texts to add to the plots:
a <- list(
text = sprintf("<b>1</b>"),
xref = "paper",
yref = "paper",
yanchor = "bottom",
xanchor = "center",
align = "center",
x = 0.5,
y = 1,
showarrow = FALSE)
b <- list(
text = sprintf("<b>2</b>"),
xref = "paper",
yref = "paper",
yanchor = "bottom",
xanchor = "center",
align = "center",
x = 0.5,
y = 1,
showarrow = FALSE)
c <- list(
text = sprintf("<b>3</b>"),
xref = "paper",
yref = "paper",
yanchor = "bottom",
xanchor = "center",
align = "center",
x = 0.5,
y = 1,
showarrow = FALSE)
Put together the actual plots, note the "annotations" option under layout. I also didn't need to add all that trace nonsense, coloring by status did the work for me.
p1 <- df_group %>%
filter(numbers == 1) %>%
group_by(letter) %>%
plot_ly(x = ~letter, y= ~n, color = ~status, type = 'bar', legendgroup = ~status) %>%
layout(barmode = 'stack', annotations = a)
p2 <- df_group %>%
filter(numbers == 2) %>%
group_by(letter) %>%
plot_ly(x = ~letter, y= ~n, color = ~status, type = 'bar', legendgroup = ~status, showlegend = FALSE) %>%
layout(barmode = 'stack', annotations = b)
p3 <- df_group %>%
filter(numbers == 3) %>%
group_by(letter) %>%
plot_ly(x = ~letter, y= ~n, color = ~status, type = 'bar', legendgroup = ~status, showlegend = FALSE) %>%
layout(barmode = 'stack', annotations = c)
Plotting:
subplot(p1, p2, p3, shareY = TRUE)
Imgur can't show interactivity, so you will just have to trust that this is interactive and you can select the categories in all plots by clicking on their labels.
I've found this question but answer is not up to date to produce the correct result.
Second Y-Axis in a R plotly graph
How can I plot a dual y axis plot?
df <- data.frame(MediaDate = as.Date(c("2016-04-01","2016-05-01","2016-06-01"), format = "%Y-%m-%d"),
Spend = c(39654, 34446, 27402),
Visits = c(19970, 14450, 12419))
plot_ly(df, x = ~MediaDate, y = ~Spend, type = "bar", name = "Spend") %>%
add_trace(x = ~MediaDate, y = ~Visits, mode = "lines", yaxis = "y2", name = "Visits") %>%
layout(yaxis2 = list(overlaying = "y", side = "right"))
Produces:
What I need (but instead of a bar and a line, 2 lines):
Here's a way to do this:
df <- data.frame(MediaDate = as.Date(c("2016-04-01","2016-05-01","2016-06-01"),
format = "%Y-%m-%d"),
Spend = c(39654, 34446, 27402),
Visits = c(19970, 14450, 12419))
old.y <- list(
side = "left",
title = "Spend"
)
new.y <- list(
overlaying = "y",
side = "right",
title = "Visits"
)
plot_ly(df) %>%
add_lines(x = ~MediaDate, y = ~Spend, yaxis="y1") %>%
add_lines(x = ~MediaDate, y = ~Visits, yaxis = "y2") %>%
layout(yaxis2 = new.y, yaxis = old.y, xaxis = list(title="MediaDate"))