18

I have a basic subplot with two graphs, both have a legend by default, but I want to see only one of them.

I tried this :

require(plotly)
p1 <- plot_ly(data=iris,x=~Sepal.Length,y=~Sepal.Width,split=~Species) %>% layout(showlegend = FALSE)
p2 <-  plot_ly(data=iris,x=~Sepal.Length,y=~Sepal.Width,split=~Species) %>% layout(showlegend = TRUE)
subplot(p1,p2)
subplot(p2,p1)

But it doesn't work : it seems as if only one showlegend attribute was handled, so if I start with p1 I have two legend, if I start with p2 I have two.

Any ideas ?

Malta
  • 1,883
  • 3
  • 17
  • 30
  • What's your `packageVersion("plotly")`? I got `‘4.5.2’` - seems to work as expected (=> one legend or no legend) – lukeA Oct 09 '16 at 20:23
  • @lukeA : same version as yours, but I haven't been clear : what I expect is to get a legend only for the p2 plot. As I understand, you get the same result I get. – Malta Oct 09 '16 at 20:50
  • Ah, now I see. You want one legend with unqiue _Species_ values and right now, they are doubled. However, I don't know how to achieve that. – lukeA Oct 10 '16 at 08:00

4 Answers4

19

I'll give you two answers, a straight one, and one for better practice and posterity (which also helps to better understand the problem) :

  1. Straight answer:
    Try to add showlegend = FALSE within the plot_ly() function, not in the layout() one. If we look at the ?subplot documentation:

    layout options found later in the sequence of plots will override options found earlier in the sequence.

    In other words, the layout showlegend option is only taken from your last plot. But using showlegend option from the plot_ly() function will affect the trace itself, saving its behavior within your subplot. Your code would now be as follows:

    require(plotly)  
    p1 <- plot_ly(data=iris,x=~Sepal.Length,y=~Sepal.Width,split=~Species,showlegend = F)
    p2 <-  plot_ly(data=iris,x=~Sepal.Length,y=~Sepal.Width,split=~Species, showlegend = T)  
    subplot(p1,p2)
    
  2. Better practice under plotly 4.0 and above.
    Use the pipe operator %>% and the group_by() function instead of split, as follows:

    p1 <-
      iris%>%
      group_by(Species)%>%
      plot_ly(x=~Sepal.Length, color= ~Species)%>%
      add_markers(y= ~Sepal.Width)
    p2 <-
      iris%>%
      group_by(Species)%>%
      plot_ly(x=~Sepal.Length, color= ~Species)%>%
      add_markers(y= ~Sepal.Width, showlegend = F)
    subplot(p1,p2)
    

This practice allows you to better understand how traces works in plotly. You can see that the data is first grouped by Species, passed to the plot_ly() function -which initializes the plot- and then you specify your trace type (markers) to actually make the plot.
Writing your code like this is easier when you want to add or remove traces and their respective options, add a grouping variable, or split/summarize your table.

rvezy
  • 555
  • 4
  • 15
19

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)
  • 5
    Thank you, this is great ! I precise that the way your data is sorted is important : if you sort your data by species for p1, and by rev(species) for p2, the graphic is the same, but when you unselect something, it doesn't suppress the same modality right and left. If you factorise using same levels, same problem, it's really the order that matter. Is it normal or is it a bug that should be reported ? – Malta Sep 14 '17 at 06:27
8

Maybe you can try a simple method. (plotly 4.9.2)

subplot(style(p1, showlegend = F), p2)

It will just show the legend of p2. Hope this works.

Ru Chern Chong
  • 3,692
  • 13
  • 33
  • 43
鄭俊杰
  • 91
  • 1
  • 2
1

There seem to be some uncertain points in the answers given until now.

First of all data frame grouping hasn't any influence as far as I can see it. It is a question of sorting not grouping (as Maltas comment above indicates). So the data frame must sorted by the variable which is intended to serve as grouping variable. But there is another pitfall which nevertheless prevents the code working. Besides the required legendgroup you have therefore to ensure

  1. that your data frame is sorted by your grouping variable (fortunately iris data are already sorted by Species),
  2. that the variables you are using don't contain missing values (NAs).

Thus this should work:

library(plotly)
p1 <-
  iris %>%
  arrange(Species) %>%
  plot_ly(x = ~Sepal.Length, color = ~Species, legendgroup = ~Species) %>%
  add_markers(y = ~Sepal.Width)
p2 <-
  iris %>%
  arrange(Species) %>%
  plot_ly(x = ~Sepal.Length, color = ~Species, legendgroup = ~Species) %>%
  add_markers(y= ~Sepal.Width, showlegend = FALSE)

subplot(p1, p2)

The following examples do not work:

  1. Sorted by wrong variable:

    p1 <-
      iris %>%
      arrange(Sepal.Length) %>%
      plot_ly(x = ~Sepal.Length, color = ~Species, legendgroup = ~Species) %>%
      add_markers(y = ~Sepal.Width)
    p2 <-
      iris%>%
      arrange(Sepal.Length) %>%
      plot_ly(x=~Sepal.Length, color= ~Species, legendgroup=~Species)%>%
      add_markers(y = ~Sepal.Width, showlegend = FALSE)
    
    subplot(p1, p2)
    
  2. Variables with missing values:

    df <- iris
    df$Sepal.Length[2] <- NA
    head(df)
    
    #>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
    #> 1          5.1         3.5          1.4         0.2  setosa
    #> 2           NA         3.0          1.4         0.2  setosa
    #> 3          4.7         3.2          1.3         0.2  setosa
    #> 4          4.6         3.1          1.5         0.2  setosa
    #> 5          5.0         3.6          1.4         0.2  setosa
    #> 6          5.4         3.9          1.7         0.4  setosa
    
    p1 <-
      df %>%
      arrange(Species) %>%
      plot_ly(x = ~Sepal.Length, color = ~Species, legendgroup = ~Species) %>%
      add_markers(y = ~Sepal.Width)
    p2 <-
     df %>%
      arrange(Species) %>%
      plot_ly(x = ~Sepal.Length, color = ~Species, legendgroup = ~Species)%>%
      add_markers(y = ~Sepal.Width, showlegend = FALSE)
    
    subplot(p1, p2)
    
giovannotti
  • 138
  • 6
  • I want to emphasize that "the data frame must sorted by the variable which is intended to serve as grouping variable". Just spent a lot of time understanding why @Mette's answer did not work on `mtcars` with `factor(cyl)` :) – janosdivenyi Feb 13 '18 at 12:01
  • 1
    It is probably due to versioning and fixes, but the two examples you said should not work now work! – Claudiu Papasteri Sep 02 '19 at 10:45