R Plotly - Cannot Order or Organize by a Variable - r

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.

Related

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

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

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.

managing colors in R for plot.ly

I am using the plot.ly library for interactive charting in a shiny app however I am running up against some trouble with managing the colors in the chart.
Reproducible example using plotly 4.3.5 (from github):
library(data.table)
library(plotly)
dt <- data.table(campaign_week = c(1,2,3,1,2,3), category = c(rep("income",3),rep("cost",3)),
amount = c(100,50,35,-500,-20,-15))
dt_net <- dt[, .(amount = sum(amount)), by = campaign_week][,.(campaign_week, amount = cumsum(amount))]
y <- list(title = "Income", tickformat = "$,.0f",hoverformat = "$,.2f")
plot_ly(dt_net, x = ~campaign_week, y = ~amount, type = "scatter",
mode= "lines+markers",
line = list(color = "#00AEFF"), name = "Net Income") %>%
add_trace(data = dt, x = ~campaign_week, y = ~amount, color = ~category, type = "bar",
colors = c("#00ff00", "#ff0000")) %>%
layout(yaxis = y, barmode = "relative")
This creates the chart that I want, however the colours aren't being applied correctly to the trace. I am expecting one of the bars to be red, and the other to be green while the line is a shade of blue.
EDIT Add a screenshot of the plotly chart created
Based on the example at https://plot.ly/r/bar-charts/#bar-chart-with-relative-barmode a separate add_trace for each category is the way to go.
plot_ly(dt_net, x = ~campaign_week, y = ~amount, type = "scatter",
mode= "lines+markers",
line = list(color = "#00AEFF"), name = "Net Income") %>%
add_trace(data = dt[category=="income",] , x = ~campaign_week, y = ~amount, type = "bar", name = "income",
marker=list(color = "#00ff00")) %>%
add_trace(data = dt[category=="cost",] , x = ~campaign_week, y = ~amount, type = "bar", name = "cost",
marker=list(color = "#ff0000")) %>%
layout(yaxis = y, barmode = "relative")
Note, this gives a warning, because the bar chart traces inherit mode and line attributes from the scatter chart, but these attributes are not supported for bars. You can either ignore the warnings, or you can call the barchart before the scatter to avoid them... Like this:
plot_ly() %>%
add_trace(data = dt[category=="income",] , x = ~campaign_week, y = ~amount, type = "bar", name = "income",
marker=list(color = "#00ff00")) %>%
add_trace(data = dt[category=="cost",] , x = ~campaign_week, y = ~amount, type = "bar", name = "cost",
marker=list(color = "#ff0000")) %>%
add_trace(data = dt_net, x = ~campaign_week, y = ~amount, type = "scatter", mode= "lines+markers",
line = list(color = "#00AEFF"), name = "Net Income") %>%
layout(yaxis = y, barmode = "relative")
I reverted the calls and added the inherit=FALSE:
library(data.table)
library(plotly)
dt <- data.table(campaign_week = c(1,2,3,1,2,3), category = c(rep("income",3),rep("cost",3)),
amount = c(100,50,35,-500,-20,-15))
dt_net <- dt[, .(amount = sum(amount)), by = campaign_week][,.(campaign_week, amount = cumsum(amount))]
y <- list(title = "Income", tickformat = "$,.0f",hoverformat = "$,.2f")
plot_ly(data=dt, x = ~campaign_week, y = ~amount, color = ~category, type = "bar",
colors = c("#00ff00", "#ff0000")) %>%
add_trace( data=dt_net, x = ~campaign_week, y = dt_net$amount, type = "scatter",
mode= "lines+markers",
line = list(color = "#00AEFF"), name = "Net Income", inherit=FALSE) %>%
layout(yaxis = y, barmode = "relative")
Still have a problem with the legend:

Resources