Change order of subplots - r

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

Related

Left-align a multi-line label using plotly

In the chart below, is there anyway to left-align all the text so that, for example, Total is located directly above Pct. Total, as shown below:
library(dplyr)
library(plotly)
library(scales)
dat <- data.frame(grp = c("A", "B", "C"),
val = c(100, 50, 50)) %>%
mutate(label = paste0("Total: ", val, "\nPct. Total: ", percent(val/sum(val))))
dat %>%
plot_ly(x = ~val,
y = ~grp,
type = "bar",
text = ~label,
textposition = "outside") %>%
layout(xaxis = list(range = c(0, 125)))
Edit: Solved
dat %>%
plot_ly(x = ~val,
y = ~grp,
type = "bar") %>%
layout(annotations = list(text = ~label,
y = ~grp,
x = ~val,
showarrow = F,
xanchor = "left",
align = "left"),
xaxis = list(range = c(0, 125)))
Solution:
dat %>%
plot_ly(x = ~val,
y = ~grp,
type = "bar") %>%
layout(annotations = list(text = ~label,
y = ~grp,
x = ~val,
showarrow = F,
xanchor = "left",
align = "left"),
xaxis = list(range = c(0, 125)))

Plotly: How to set a minimum value on secondary y-axis?

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

R-plotly: Subplot shows only bottom plot

I would like to reproduce the "Scaled Subplots" in https://plot.ly/r/subplots/ for the mtcars data.
mtcars %>%
transform(id = as.integer(factor(am))) %>%
plot_ly(x = ~mpg, y = ~qsec, color = ~factor(vs), yaxis = ~paste0("y", id)) %>%
add_markers() %>%
subplot(nrows = 2, shareX = TRUE)
Only the bottom subplot shows up:
I thought that I did faithfully copy/translated the code, but something must be wrong.
Of note, the subplot discriminates am, whereas the color discriminates vs.
I tried am for both the subplot and the color:
mtcars %>%
transform(id = as.integer(factor(am))) %>%
plot_ly(x = ~mpg, y = ~qsec, color = ~am, yaxis = ~paste0("y", id)) %>%
add_markers() %>%
subplot(nrows = 2, shareX = TRUE)
It does not help much, but the two grids appear:
On the latter example, I expected the am==0 (blueish) dots to be in the top subplot.
Any suggestion?
packageVersion('plotly')
[1] ‘4.9.0’
Well, this way here you can do this, but must create two plots and than use subplot()
p1 = mtcars %>%
filter(am==0) %>%
plot_ly(x = ~mpg, y = ~qsec, color = ~vs, legendgroup = "am0", name = "0",
type = "scatter" , mode = "markers", showlegend = FALSE)
p2 = mtcars %>%
filter(am==1) %>%
plot_ly(x = ~mpg, y = ~qsec, color = ~vs, legendgroup = "am1", name = "1",
type = "scatter" , mode = "markers")
subplot(p1,p2,nrows = 2, shareX = TRUE, titleY = TRUE, which_layout = 1)
Here the output:

Sharing axes and legends between subplots in plotly in R (faceting in ggplot2 and using ggplotly doesn't work)

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.

R: plotly graph with dual Y axis?

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"))

Resources