In R plotly subplot graph, how to show only one legend?
The above answer results in a minor problem. The legend is only interactive with the first plot. You need to add the legendgroup to the plot_ly function to make the legend interactive with both plots.
library(plotly)
p1 <-
iris%>%
group_by(Species)%>%
plot_ly(x=~Sepal.Length, color= ~Species, legendgroup=~Species)%>%
add_markers(y= ~Sepal.Width)
p2 <-
iris%>%
group_by(Species)%>%
plot_ly(x=~Sepal.Length, color= ~Species, legendgroup=~Species)%>%
add_markers(y= ~Sepal.Width, showlegend=F)
subplot(p1,p2)
Single legend for Plotly subplot for line plots created from two data frames in R
This can be achieved by first bringing the data in the right shape which also simplifies the plotting. Simply row bind your dfs e.g. via dplyr::bindrows
and you have the variable you need for setting up the legendgroup
. Also, your colors don't reflect the variables y and z but the datasets. Try this:
library(dplyr)
library(plotly)
d1 <- data.frame(x = 1:5,
y = c(2, 3, 4, 1, 5),
z = c(2, 1, 4, 6, 8))
d2 <- data.frame(x = 1:5,
y = c(1, 5, 8, 9, 11),
z = c(3, 5, 8, 13, 11))
# Bind the dfs
d3 <- bind_rows(list(d1 = d1, d2 = d2), .id = "id")
py <- d3 %>%
plot_ly(x = ~x, y = ~y, color = ~id, legendgroup= ~id) %>%
add_lines(colors = c("#D55E00", "#56B4E9"))
pz <- d3 %>%
plot_ly(x = ~x, y = ~z, color = ~id, legendgroup= ~id) %>%
add_lines(colors = c("#D55E00", "#56B4E9"), showlegend = FALSE)
subplot(py, pz) %>%
layout(legend=list(title=list(text='<b> Dataset </b>')))
Created on 2020-04-10 by the reprex package (v0.3.0)
Legend near each plot in subplot plot_ly in R
This is not achievable as of yet, as per this. This is far from a perfect hack, but if you wished, something like this may be workable -
Use n
to identify the number of unique elements in your colouring variable.
library(plotly)
n <- 3L
clrs <- colorRampPalette(
c(rgb(r = 198, g = 89, b = 17, maxColorValue = 255), '#267dff', 'black')
)(n)
annotations <- c('setosa', 'versicolor', 'virginica')
y_annotation <- seq(0.4, 0.6, length.out = n)
p1 <-
iris %>%
group_by(Species) %>%
plot_ly(x = ~Sepal.Length, color = ~Species, showlegend = FALSE, colors = clrs) %>%
add_markers(y= ~Sepal.Width) %>%
layout(margin = list(r = 100))
for (i in seq_along(annotations)) {
p1 <- add_annotations(
p = p1, text = annotations[i], font = list(color = clrs[i]),
x = 1.05, y = y_annotation[i], xref = 'paper', yref = 'paper',
showarrow = FALSE, xanchor = 'left'
)
}
p2 <-
iris%>%
group_by(Species) %>%
plot_ly(x = ~Sepal.Length, color = ~Species, showlegend = FALSE, colors = clrs) %>%
add_markers(y = ~Sepal.Width) %>%
layout(margin = list(r = 100))
for (i in seq_along(annotations)) {
p2 <- add_annotations(
p = p2, text = annotations[i], font = list(color = clrs[i]),
x = 1.05, y = y_annotation[i], xref = 'paper', yref = 'paper',
showarrow = FALSE, xanchor = 'left'
)
}
subplot(p1, p2, nrows = 2, shareX = T, shareY = F, titleX = T, titleY = T)
This would result in a plot like below.
Looping through R Plotly with subplot and hiding all legend except one
There are two issues in your code:
i
is not1:3
but your current tibble you are iterating through via lapply (seeseq_along
below).
That is why you get the warning:
In if (i == 1) { : the condition has length > 1 and only the first
element will be used
showlegend
needs to be an argument toplot_ly
not tolayout
because subplot always adopts thelayout
from one of its plots. see?subplot
and its argumentwhich_layout
.
layout options found later in the sequence of plots will override
options found earlier in the sequence
Here is what I think you are after:
library(plotly)
library(dplyr)
tibble_list <- mtcars %>%
mutate(vs = as.factor(vs)) %>%
group_split(cyl)
lapply(seq_along(tibble_list), function(i) {
show_legend <- if (i == 1) {TRUE} else {FALSE}
plot_ly(
data = tibble_list[[i]],
x = ~ gear,
y = ~ mpg,
color = ~ vs,
type = "bar",
legendgroup = ~ vs,
showlegend = show_legend
) %>% layout(barmode = "stack")
}) %>% subplot(
nrows = NROW(.),
shareX = TRUE,
shareY = TRUE,
titleX = TRUE,
titleY = TRUE,
margin = 0.05,
which_layout = 1
)
Please find an offical example here.
Avoiding duplicate legends with R plotly subplot results in missing points
Does this help? I think the issue was in the way you had specified size
. The attribute marker
controls the size of the points.
require(plotly)
set.seed(1)
a <- data.frame(x=1:3, y=1:3)
b <- data.frame(x=(1:3)+.1, y=(1:3)+.1)
xu <- runif(1000, 0, 3)
xn <- (rnorm(1000) + 3) / 2
co <- 'black'
p <- plot_ly()
# attribute 'marker' controls size of points
pa <- add_markers(p,
data=a, x=~x, y=~y, name='j', legendgroup='j',
marker = list(size = 5), color=I(co),
showlegend=FALSE)
pb <- add_markers(p,
data=b, x=~x, y=~y, name='j', legendgroup='j',
marker = list(size = 5), color=I(co),
showlegend=TRUE)
pc <- add_histogram(p, x=~xu, name='k', color=I('black'),
legendgroup='k', showlegend=FALSE)
pd <- add_histogram(p, x=~xn, name='k', color=I('black'),
legendgroup='k', showlegend=TRUE)
plotly::subplot(pa, pb, pc, pd, shareX=TRUE, shareY=FALSE, titleX=TRUE, nrows=4)
Note that mode = 'markers'
(note the plural) is not required if you're using add_markers
. It is, however, required if you use the more general add_trace
.
Using plotly's subplot function with a shared legend, have each group appear only once in the legend
I suggest a solution with a detour via ggplot2. Hope this helps for your purpose.
library(tidyverse)
library(plotly)
df1 <- data.frame(col1 = rep(LETTERS[1:3], each = 4), col2 = rnorm(12), col3 = runif(12), col4 = rep(c("Fred", "Bob"), each = 6))
p <- ggplot(df1, aes(col2, col3)) + geom_point(aes(color = col4)) + facet_wrap("col1")
plotly::ggplotly(p)
Related Topics
Devtools::Install_Github() - Ignore Ssl Cert Verification Failure
Use an Image as Area Fill in an R Plot
How to Add a Page Break in Word Document Generated by Rstudio & Markdown
In R, How to Check If Two Variable Names Reference the Same Underlying Object
Ggplot: How to Set Default Color for All Geoms
How to Turn Gpclibpermit() to True
Ggplot2 - Using Two Different Color Scales for Overlayed Plots
Correctly Color Vertices in R Igraph
Gsub in R with Unicode Replacement Give Different Results Under Windows Compared with Unix
How to Produce a Heatmap with Ggplot2
Nested If Else Statements Over a Number of Columns
Filter a Vector of Strings Based on String Matching
Expression and New Line in Plot Labels
Minus Operation of Data Frames
Applying a Function to Each Row of a Data.Table
Rcpp Function to Select (And to Return) a Sub-Dataframe
List Members Can Be Accessed with Partial Name? Is This a Feature