R-plotly: Subplot shows only bottom plot - r

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:

Related

R Plotly - Cannot Order or Organize by a Variable

I am trying to create a Plotly plot in R, and I cannot seem to get it to break the data down by the "class" variable.
This data is built into R, so it should be easy for anyone to look at.
First, here is the code (I added quotation marks around "class" in a few spots, because the code will not run otherwise):
library(plotly)
library(tidyverse)
mpg %>%
group_by(model) %>%
summarise(c = mean(cty), h = mean(hwy), class = class) %>%
mutate(model = forcats::fct_reorder(model, c), class = forcats::fct_reorder(class, c)) %>%
plot_ly() %>%
add_segments(
x = ~c, y = ~forcats::fct_reorder(model, c),
xend = ~h, yend = ~model,
color = "class", showlegend = TRUE
) %>%
add_markers(
x = ~c, y = ~model,
marker = list(symbol = "square",
color = "class"),
name = "",
showlegend = FALSE
) %>%
add_markers(
x = ~h, y = ~model,
marker = list(symbol = "diamond",
color = "class"),
name = "",
showlegend = FALSE
) %>%
layout(xaxis = list(title = "Miles per gallon"))
I am trying to get the data to be ordered by the new "c" variable overall, but I want to be able to break the data down by the "class" (the type of vehicle). However, as you can see from the code, every car is the same color, so that isn't happening?
I appreciate any help I can get here. I am pretty new to Plotly, so I could definitely be overlooking something simple.
Thank you!
Instead of mapping the string constant "class" on color, map the class column on the color attribute:
library(plotly)
library(tidyverse)
mpg %>%
group_by(model) %>%
summarise(c = mean(cty), h = mean(hwy), class = class) %>%
mutate(model = forcats::fct_reorder(model, c), class = forcats::fct_reorder(class, c)) %>%
plot_ly() %>%
add_segments(
x = ~c, y = ~forcats::fct_reorder(model, c),
xend = ~h, yend = ~model,
color = ~class, showlegend = TRUE
) %>%
add_markers(
x = ~c, y = ~model, color = ~class,
marker = list(symbol = "square"),
name = "",
showlegend = FALSE
) %>%
add_markers(
x = ~h, y = ~model, color = ~class,
marker = list(symbol = "diamond"),
name = "",
showlegend = FALSE
) %>%
layout(xaxis = list(title = "Miles per gallon"))
#> `summarise()` has grouped output by 'model'. You can override using the
#> `.groups` argument.

How to add exactly same right axis on plotly R chart?

I have this basic script:
mtcars %>%
plot_ly() %>%
add_trace(x = ~mpg, y = ~wt, type = 'scatter', mode = 'markers' ) %>%
layout(yaxis2 = list(overlaying = "y", side = "right", title = 'test'))
It plots the chart with one axe on the left even though there is a command in layout to add a second chart.
I suppose it doesn't get triggered because nothing is plotted.
So I add the same variable
mtcars %>%
plot_ly() %>%
add_trace(x = ~mpg, y = ~wt, type = 'scatter', mode = 'markers' ) %>%
add_trace(x = ~mpg, y = ~wt, type = 'scatter', mode = 'markers', yaxis = "y2" ) %>%
layout(yaxis2 = list(overlaying = "y", side = "right", title = 'test'))
And in this case both left and right axis are the same.
I suppose I could just do the second series transparent or something.
Is there a more clean solution to force the second axis to show even though nothing is plotted on it?
Try something like this:
library(plotly)
#Code
mtcars %>%
plot_ly() %>%
add_trace(x = ~mpg, y = ~wt, type = 'scatter', mode = 'markers' ) %>%
add_trace(x = ~mpg, y = ~wt, type = 'scatter', mode = 'markers',
yaxis = "y2") %>%
layout(yaxis2 = list(overlaying = "y", side = "right", title = 'test'))
Output:
Old question, but anyway:
You can't display an axis without assigning a trace to it.
However, you don't need to use the entire data again - you can simply create datapoints based on range() to achive the same an hide the trace via the opacity and showlegend parameters (using visible would prevent showing the axis):
library(plotly)
mtcars %>%
plot_ly() %>%
add_trace(x = ~mpg, y = ~wt, type = 'scatter', mode = 'markers') %>%
add_trace(x = ~range(mpg), y = ~range(wt), type = 'scatter', mode = 'markers', yaxis = "y2", opacity = 0, showlegend = FALSE) %>%
layout(showlegend = TRUE, yaxis2 = list(overlaying = "y", side = "right", title = 'test'))

How can I hide a trace in a legend in R plotly

I have a plotly graph with several traces. Some of them I don't want to appear in the legend. How do I do this?
You need to set showlegend = F in your trace:
CODE
library(plotly)
plt <- plot_ly(as.data.frame(mtcars)) %>%
add_markers(x = ~wt, y = ~mpg, name = 'Fuel Eff.', type = 'scatter') %>%
add_markers(x = ~wt, y = ~hp, name = 'Power to wt. ratio', type = 'scatter',
showlegend = F) %>%
layout(
showlegend = T,
legend = list(orientation = 'h')
)
Output

Change order of subplots

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

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.

Resources