Hot questions for Using Ggplot2 in ggplotly

Question:

I have a simple data frame:

seq <- 1:10
name <- c(paste0("company",1:10))
value <- c(250,125,50,40,40,30,20,20,10,10)
d <- data.frame(seq,name,value)

And I want to plot it this way:

require(ggplot2)
ggplot(data = d,aes(x=seq,y=value))+geom_line() + geom_point()

Now I want to use plotly, mostly to be able, when mousing over a point, to get other information than the value, such as the company name. I try this :

require(plotly)
ggplotly()

which get me a tooltip, but with only seq and value. I tried the option tooltip= but it's specified you can use the only variable describe in the aesthetic, and I don't use the name in my aes.

Any solution? I saw I am not the first with this problem, but I haven't found answer working with ggplotly.


Answer:

You don't need to modify the plotly object as suggested by @royr2. Just add label = name as third aesthetic

ggplot(data = d, aes(x = seq, y = value, label = name)) + geom_line() + geom_point()

and the tooltip will display name in addition to seq and value.

The ggplotly help file says about tooltip parameter:

The default, "all", means show all the aesthetic mappings (including the unofficial "text" aesthetic).

So you can use the label aesthetic as long as you don't want to use it for geom_text.

BTW: I've also tried text instead of label

ggplot(data = d, aes(x = seq, y = value, text = name)) + geom_line() + geom_point()

but then ggplot2 complained

geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?

and plotted only points. I had to add a dummy group to geom_line to remove the issue:

ggplot(data = d, aes(x = seq, y = value, text = name)) + geom_line(group = 1) + geom_point()

(But note if you put the dummy group as fourth aesthetic inside aes() it will appear by default also in the tooltip.)

However, I find the unofficial text aesthetic can become useful alongside label if you want to have different strings plotted by geom_text and shown in the tooltip.

Edit to answer a question in comments: The tooltip parameter to ggplotly() can be used to control the appearance. ggplotly(tooltip = NULL) will suppress tooltips at all. ggplotly(tooltip = c("label")) selects the aesthetics to include in the tooltip.

Question:

I am struggling with text formatting when using ggplotly and the mouse over functionality.

library(plotly)
df <- data.frame(a=letters, b=LETTERS, x=runif(26), y=runif(26))
g <- ggplot(df, aes(x,y)) + geom_point(aes(text=sprintf('letter: %s\nLetter: %s', a, b)))
g
(gg <- ggplotly(g))

I would like to have some formatted text or at least a newline in my mouse over label. Is there a good documentation on how to design this mouse over bubble thing?


Answer:

See the tooltip argument to ggplotly(). For instance, to show only the species name (e.g. virginica for the top right point) on hover:

g <- ggplot(tail(iris), aes(Petal.Length, Sepal.Length, text=Species)) + geom_point()
ggplotly(g, tooltip="text")

Other examples:

ggplotly(g, tooltip="x")             # Petal.Length: 5.7
ggplotly(g, tooltip="Petal.Length")  # Petal.Length: 5.7
ggplotly(g, tooltip=c("x", "y"))

The last example will show the two-line tooltip

Petal.Length: 5.7
Sepal.Length: 6.7

Question:

Assume data

library(ggplot2)
library(plotly)

set.seed(357)
xy <- data.frame(letters = rep(c("a", "b", "c"), times = 3),
                 values = runif(9),
                 groups = rep(c("group1", "group2", "group3"), each = 3))

  letters    values groups
1       a 0.9913409 group1
2       b 0.6245529 group1
3       c 0.5245744 group1
4       a 0.4601817 group2
5       b 0.2254525 group2
6       c 0.5898001 group2
7       a 0.1716801 group3
8       b 0.3195294 group3
9       c 0.8953055 group3

ggplotly(
  ggplot(xy, aes(x = letters, y = values, group = groups)) +
  theme_bw() +
  geom_point()
)

My goal is to, on hover, highlight all points that belong to the same group. E.g. on hover over the point in the upper right corner, all points from this group (circles) would turn red. Something similar can be achieved using layout(hovermode = "x") but only if one is interested in highlighting all points on one of the axes. I would like the same behavior for custom variable other than x, y or closest (which are modes of hovermode).


Answer:

this will probably suit your needs

sample data

set.seed(357)
xy <- data.frame(letters = rep(c("a", "b", "c"), times = 3),
                 values = runif(9),
                 groups = rep(c("group1", "group2", "group3"), each = 3))

plotting

#create a SharedData object for use in the ggplot below, group by 'groups' 
d <- highlight_key(xy, ~groups )

#create a normal ggplot to fit your needs, but use the SharedData object as data for the chart
p <- ggplot( d, aes(x = letters, y = values, group = groups)) + theme_bw() + geom_point()

#now ggplotly the newly created ggplot, and add text for the tooltips as needed
gg <- ggplotly( p, tooltip = "groups" )

#set the highlight-options to your liking, and plot...
highlight( gg, on = "plotly_hover", off = "plotly_deselect", color = "red" )

plot results

Question:

I tried to plot series of interactive ggplotly graphs from inside for loop in R markdown (.Rmd) file. Contents of my .Rmd file:

---
title: "Untitled"
output: html_document
---

```{r}
library(ggplot2) # for plots
library(plotly)  # for interactive plots

# Convert 4 variables to factor variables:
factor_vars <- c("vs", "am", "gear", "carb")
mtcars[factor_vars] <- data.frame(Map(as.factor, mtcars[factor_vars])) 



for (VAR in factor_vars) {
    cat(paste("Factor variable:", VAR))
    # Contents of "VAR" changes inside the loop
    p <- ggplot(mtcars, aes_string(x = "mpg", y = "wt", color = VAR)) + geom_point()

    # Print an interactive plot
    print(ggplotly(p))
}

```

I push Knit HTML button in RStudio. Unfortunately, none of interactive plots appear in the .html file.

Question: why the graphs aren't plotted? And how can I create interactive plot in combination with for loop in Rmd file?

p.s. If I use print(p) instead of print(ggplotly(p)), ggplot2 plots appear in resulting .html file.


Answer:

Based on this github issue, you should be able to do something like this:

  ---
  title: "Untitled"
  output: html_document
  ---

  ```{r, message = F}
  library(ggplot2) # for plots
  library(plotly)  # for interactive plots

  # Convert 4 variables to factor variables:
  factor_vars <- c("vs", "am", "gear", "carb")
  mtcars[factor_vars] <- data.frame(Map(as.factor, mtcars[factor_vars])) 

  plt <- htmltools::tagList()
  i <- 1
  for (VAR in factor_vars) {

      # Contents of "VAR" changes inside the loop
      p <- ggplot(mtcars, aes_string(x = "mpg", y = "wt", color = VAR)) + 
        geom_point() + 
        ggtitle(paste("Factor variable:", VAR))


      # Print an interactive plot
      # Add to list
      plt[[i]] <- as.widget(ggplotly(p))
      i <- i + 1
  }

  ```

  ```{r, echo = F}
  plt
  ```

Question:

I have a plot that I am rendering in shiny using plotly and ggplot2. However, I do not want the option bar that appears on hover to appear. Is there a way to use ggplotly(p) and remove the option bar?


Answer:

There is a great answer on community plotly the short version:

library(plotly)
set.seed(100)
d <- diamonds[sample(nrow(diamonds), 1000), ]

Using ggplotly:

p <- ggplot(d, aes(carat, price)) + geom_point()
ggplotly(p) %>% config(displayModeBar = F)

If you are not using ggplotly you can do:

plot_ly(d, x = carat, y = price, text = paste("Clarity: ", clarity),
mode = "markers", color = carat, size = carat) %>% config(displayModeBar = F)

Question:

I'm trying to render a simple geom_line with a tooltip defined by a text aesthetic.

q <- ggplot(data = graphDataFactor(), aes(x = Dates,
                                          y=Variable_Data, 
                                          colour = Variable_Name
                                          #,
                                        #text = paste('Date: ', as.Date(Dates),
                                        #'<br>Variable:', Variable_Name,
                                        #'<br>Var Unit:', Variable_Data
                                                  #)
                                                  )) + 
          geom_line(size = 1) + 
          labs(colour = "Variables") 
ggplotly(q
         #, tooltip = c("text")
         )

So this code with the text aesthetic commented out works fine and renders the line. However, when I try to use the text aesthetic and tooltip, the geom_line does not appear in the plot. Hovering over the correct locations does show the right tooltip, and the colour legend displays properly.

Also, I have an identical call where the only difference is that I call geom_point rather than geom_line and that renders perfectly fine.

Is this just a bug with ggplotly or is there something wrong with my code?


Answer:

Add group=1 when setting aesthetics.

library(plotly)
set.seed(1234)
df <- data.frame(Dates = c("01/14/92", "02/27/92", "03/27/92", "04/28/92", "01/03/92"),
                 Variable_Data=runif(5), Variable_Name=c("A","A","A","B","B"))
df$Dates <- as.Date(df$Dates,"%m/%d/%y")

q <- ggplot(data = df, aes(x=Dates, y=Variable_Data, 
                           colour=Variable_Name, group=1,
     text = paste('Date: ', Dates,
                  '<br>Variable:', Variable_Name, 
                  '<br>Var Unit:', Variable_Data))) + 
     geom_line(size = 1) + labs(colour = "Variables") 

ggplotly(q, tooltip = "text")

Question:

I am trying to use ggplotly to add interactivity to my ggplot chart. I have tried running this in both RStudio and from the command line, with the same results.

Data:

library(plotly)
df1 <- as.data.frame(list('x'=1:100,'y'=1:100,'lw'=abs(rnorm(100))))
b <- ggplot(data=df1, aes(x=x,y=y)) + geom_line(size=df1$lw)

If I display b normally, i.e. > b, I get a correct plot

However, if I then enter ggplotly(), I get the plot below:

Using my real data, the results are even worse. Below is a plot(), which is correct, followed by ggplotly()

Any idea how I can display this correctly?


Answer:

Although this is caused by a bug in plotly (see comment from takje), you can work around this bug by treating your plot not as a single line with multiple widths, but as many line segments, each with a fixed width.

First, set up the data:

library(ggplot2)
library(plotly)
set.seed(123)
df1 <- as.data.frame(list('x'=1:100,'y'=1:100,'lw'=abs(rnorm(100))))

Now we construct a new data frame that contains the start and end points of each line segment. I.e. nth line segment goes from (x_n,y_n) to (x_n+1, y_n+1). The repetition (rep) in the following code is because intermediate points form the endpoint of one segment, and also the start-point of the next. The first and last points of the whole set are not repeated because they appear only in a single line segment:

x2 <- c(df1$x[1], rep(df1$x[2:(NROW(df1)-1)], each=2),  df1$x[NROW(df1)])
y2 <- c(df1$y[1], rep(df1$y[2:(NROW(df1)-1)], each=2),  df1$y[NROW(df1)])
df2 <- data.frame(x2,y2)

Next, we label each of the x, and y coordinates with a segnum label, that refers to which line segment they are in:

df2$segnum <- rep(1:(NROW(df1)-1), each=2)

and another vector that corresponds to these segment numbers, and contains the line width for each segment:

df2$segw <- rep(df1$lw[1:(NROW(df1)-1)], each=2)

and plot:

ggplot(data=df2, aes(x=x2,y=y2, colour=segnum)) + geom_line(aes(group = segnum, size=segw))

Also in plotly:

ggplotly()

Question:

I've got an issue when using ggplotly() to a ggplot graph: the y axis disappears. Here's a reproducible example using iris dataset (this example is quite dump, but whatever)

data(iris)
g = ggplot(data = iris, aes(x = Petal.Length, y = Petal.Width, fill = Species)) + 
  geom_bar(stat = "identity", position = "dodge") + 
  scale_fill_manual(name = "legend", values = c("blue", "red", "green")) +
  ylab("Y title") +
  ylim(c(0,3)) +
  xlab("X title") +
  ggtitle("Main title")
g
ggplotly(g)

As you can see, the Y axis title vanished.

Well, if ylim is deleted it works, but I'd like to specify y limits.

I tried to do the following:

data(iris)
g = ggplot(data = iris, aes(x = Petal.Length, y = Petal.Width, fill = Species)) + 
  geom_bar(stat = "identity", position = "dodge") + 
  scale_fill_manual(name = "legend", values = c("blue", "red", "green")) +
  scale_y_continuous(name = "Y title", limits = c(0, 3)) +
  xlab("X title") +
  ggtitle("Main title")
g
ggplotly(g)

But now it's the legend title that doesn't fit.

My config : R 3.2.0, plotly 2.0.16, ggplot2 2.0.0

In both examples the graph given by ggplot is what I want, but ggplotly gives something else. Is it an issue, is there a workaround?


Answer:

I am not sure why it's happening but here is a work around. It will give you what you want.

p <- ggplotly(g)
x <- list(
    title = "X Title"
)
y <- list(
    title = "Y Title"
)
p %>% layout(xaxis = x, yaxis = y)

Question:

I'm making some figures with ggplotly() and have noticed that facet_wrap and facet_grid causes each item in the legend to be repeated by the number of facets. Is there a way to stop this?

For example:

library("ggplot2")
library("plotly")
diamonds = diamonds[diamonds$cut %in% c("Fair", "Good"),]
dia = ggplot(diamonds, aes(x = cut)) + 
  geom_bar(aes(stat = "identity", fill = cut)) + 
  facet_grid(.~color)

ggplotly(dia)

The ?plotly documentation isn't very elaborate, and none of these have legends.

Here's what comes up when I just type ggplotly if that gives any insight:

function (p = ggplot2::last_plot(), filename, fileopt, world_readable = TRUE) 
{
    l <- gg2list(p)
    if (!missing(filename)) 
        l$filename <- filename
    if (!missing(fileopt)) 
        l$fileopt <- fileopt
    l$world_readable <- world_readable
    hash_plot(p$data, l)
}

Answer:

UPDATE

Issues appear fixed with Plotly 3.6.0 -- 16 May 2016

Due to the ggplotly bug for geom_bar, which distorts the data for the bars, there may not be a good way to do this. For this particular case, facet is not needed. You can use plot_ly() to build an effective plot.

Plot_ly
require(plotly)
require(dplyr)

d <- diamonds[diamonds$cut %in% c("Fair", "Good"),] %>%
  count(cut, color)

plot_ly(d, x = color, y = n, type = "bar", group = cut)

Use Plotly subplot()

If this plot type is a must, you can build a facet-like plot using Plotly's subplot. It's not pretty.

d2 <- diamonds[diamonds$cut %in% c("Fair", "Good"),] %>%
  count(cut, color) %>%
  transform(color = factor(color, levels=rev(levels(color)))) %>%
  mutate(id = as.integer(color)) 

p <- plot_ly(d2, x = cut, y = n, type = "bar", group = color, xaxis = paste0("x", id), marker = list(color = c("#0000FF","#FF0000"))) %>%
  layout(yaxis = list(range = range(n), linewidth = 0, showticklabels = F, showgrid = T, title = ""),
         xaxis = list(title = ""))

subplot(p) %>%
  layout(showlegend = F,
         margin = list(r = 100),
         yaxis = list(showticklabels = T),
         annotations = list(list(text = "Fair", showarrow = F, x = 1.1, y = 1, xref = "paper", yref = "paper"),
                            list(text = "Good", showarrow = F, x = 1.1, y = 0.96, xref = "paper", yref = "paper")),
         shapes = list(list(type = "rect", x0 = 1.1, x1 = 1.13, y0 = 1, y1 = 0.97, line = list(width = 0), fillcolor = "#0000FF", xref = "paper", yref = "paper"),
                       list(type = "rect", x0 = 1.1, x1 = 1.13, y0 = 0.96, y1 = 0.93, line = list(width = 0), fillcolor = "#FF0000", xref = "paper", yref = "paper")))

Question:

I am trying to build a plot combining ggplot2 and plotly. The two vertical lines appear on pure ggplot2, but once I call plotly::ggplotly on it, they go away. How can I make the data also appear on the ggplotly version? If you have a solution using only plot_ly, that would be fine too.

The data:

df <- structure(list(date = structure(c(17226, 17257, 17287, 17318, 
17348, 17379, 17410, 17440, 17471, 17501, 17226, 17257, 17287, 
17318, 17348, 17379, 17410, 17440, 17471, 17501, 17226, 17257, 
17287, 17318, 17348, 17379, 17410, 17440, 17471, 17501), class = "Date"), 
    n = c(253L, 217L, 257L, 166L, 121L, 56L, 68L, 62L, 142L, 
    20L, 174L, 228L, 180L, 158L, 80L, 39L, 47L, 54L, 107L, 12L, 
    93L, 74L, 47L, 49L, 55L, 16L, 52L, 53L, 32L, 3L), act = c("a", 
    "a", "a", "a", "a", "a", "a", "a", "a", "a", "b", "b", "b", 
    "b", "b", "b", "b", "b", "b", "b", "c", "c", "c", "c", "c", 
    "c", "c", "c", "c", "c")), class = "data.frame", row.names = c(NA, 
-30L), .Names = c("date", "n", "act"))

facts_timeline <- structure(list(Date = structure(c(17507, 17293), class = "Date"), 
    ShortDescription = c("Marketing Campaign", "Relevant Fact 1"
    )), row.names = c(NA, -2L), class = c("tbl_df", "tbl", "data.frame"
), spec = structure(list(cols = structure(list(Date = structure(list(
    format = ""), .Names = "format", class = c("collector_date", 
"collector")), Tenant = structure(list(), class = c("collector_character", 
"collector")), ShortDescription = structure(list(), class = c("collector_character", 
"collector")), LongDescription = structure(list(), class = c("collector_character", 
"collector"))), .Names = c("Date", "Tenant", "ShortDescription", 
"LongDescription")), default = structure(list(), class = c("collector_guess", 
"collector"))), .Names = c("cols", "default"), class = "col_spec"), .Names = c("Date", 
"ShortDescription"))

The code to make the plot:

p <- df %>% 
  ggplot(aes(date, n, group = act, color = act)) + 
  geom_line() + 
  geom_vline(data = facts_timeline, aes(xintercept = Date))

Here you can see the two vertical lines:

p

But not here:

ggplotly(p)

Answer:

Simply set the xintercept to numeric, and everything will work.

p <- df %>% 
  ggplot(aes(date, n, group = act, color = act)) + 
  geom_line() + 
  geom_vline(data = facts_timeline, aes(xintercept = as.numeric(Date)))

p

ggplotly(p)

Question:

I am trying to create a plotly graph for a shiny app. I am running into an issue with certain layouts of faceted plots. Whenever there are four facets and they are in a 2x2 grid, the bottom left facet does not display any data even though the data is there in the ggplot figure. This also happens when there are 6 facets in a 3x2 grid, with the bottom left again being dropped. The examples on the plotly ggplot examples page show several examples with a 2x2 grid and the data being displayed. I am not sure what the issue is. Any help is much appreciated.

Code:

library(ggplot2)
library(dplyr)
library(plotly)

data %>%
  filter(!is.na(result)) %>%
  ggplot(aes(date_time, result)) +
  facet_wrap(~group, scales = "free_y") +
  geom_point() +
  geom_line()


ggplotly()

ggplot output:

ggplotly output:

Data:

data <- structure(list(group = c("w", "w", "w", "w", "w", "w", "w", 
                                 "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", 
                                 "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", 
                                 "y", "y", "y", "y", "y", "y", "y", "y", "y", "y", "y", "y", "y", 
                                 "y", "y", "y", "y", "y", "y", "y", "y", "y", "y", "y", "y", "y", 
                                 "y", "y", "y", "y", "y", "y", "y", "x", "x", "x", "x", "x", "x", 
                                 "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", 
                                 "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", 
                                 "x", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", 
                                 "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", 
                                 "z", "z", "z", "z", "z", "z", "z", "z"), 
                   date_time = structure(c(1501581060, 1501668000, 1501752000, 
                                           1501837740, 1502101200, 1502184600, 1502271840, 
                                           1502357280, 1502442720, 1502701860, 1502789280, 
                                           1502876340, 1502961600, 1503047640, 1503305520, 
                                           1503394200, 1503480900, 1503567600, 1503651300, 
                                           1503915120, 1503997800, 1504086300, 1504171920, 
                                           1504259100, 1504607100, 1504691040, 1504777500,
                                           1504865820, 1505122680, 1505211600, 1505296560, 
                                           1505382720, 1505470140, 1501581060, 1501668000, 
                                           1501752000, 1501837740, 1502101200, 1502184600, 
                                           1502271840, 1502357280, 1502442720, 1502701860, 
                                           1502789280, 1502876340, 1502961600, 1503047640, 
                                           1503305520, 1503394200, 1503480900, 1503567600, 
                                           1503651300, 1503915120, 1503997800, 1504086300, 
                                           1504171920, 1504259100, 1504607100, 1504691040, 
                                           1504777500, 1504865820, 1505122680, 1505211600, 
                                           1505296560, 1505382720, 1505470140, 1501581060, 
                                           1501668000, 1501752000, 1501837740, 1502101200, 
                                           1502184600, 1502271840, 1502357280, 1502442720, 
                                           1502701860, 1502789280, 1502876340, 1502961600, 
                                           1503047640, 1503305520, 1503394200, 1503480900, 
                                           1503567600, 1503651300, 1503915120, 1503997800, 
                                           1504086300, 1504171920, 1504259100, 1504607100, 
                                           1504691040, 1504777500, 1504865820, 1505122680, 
                                           1505211600, 1505296560, 1505382720, 1505470140, 
                                           1501581060, 1501668000, 1501752000, 1501837740, 
                                           1502101200, 1502184600, 1502271840, 1502357280, 
                                           1502442720, 1502701860, 1502789280, 1502876340, 
                                           1502961600, 1503047640, 1503305520, 1503394200, 
                                           1503480900, 1503567600, 1503651300, 1503915120, 
                                           1503997800, 1504086300, 1504171920, 1504259100, 
                                           1504607100, 1504691040, 1504777500, 1504865820, 
                                           1505122680, 1505211600, 1505296560, 1505382720, 
                                           1505470140), 
                                         class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
                   result = c(2.1, 1.75, 1.65, 1.65,  1.75, 1.65, 1.3, 1.65, 1.9, 1.6, 1.65, 
                              1.35, 1.6, 1.85, 2.05,  1.95, 2, 1.95, 1.9, 1.9, 2.05, 2, 2, 
                              2, 2.1, 2.1, 2, 2.05, 2.05, 2.3, 2.2, 2, NA, 7.14, 7.1, 7.09, 
                              7.09, 7.13, 7.12, 7.13, 7.07, 7.04, 7.06, 7.12, 7.08, 7.06, 
                              7.07, 7.05, 7.05, 7.1, 7.09, 7.06, 7.18, 7.16, 7.11, 7.17, 
                              7.14, 7.13, 7.08, 7.11, 7.09, 7.12, 7.05,  7.08, 7.02, 7.12, 
                              0.214, 0.181, 0.357, 0.49, 0.294, 0.369, 0.406, 0.325, 0.197, 
                              0.36, 0.358, 0.408, 0.37, 0.254, 0.24, 0.178, 0.201, 0.166, 0.203, 
                              0.163, 0.147, 0.177, 0.155, 0.177, 0.133, 0.133, 0.182, 0.203, 
                              0.161, 0.151, 0.171, 0.117, NA, 26, 26, 26, 26, 25, 26, 25, 26, 
                              26, 26, 26, 25, 26, 26, 25, 26, 26, 26, 26, 26, 26, 26, 26, 25, 
                              25, 24, 24, 24, 23, 23, 23, 24, 23)), 
              .Names = c("group", "date_time", "result"), 
              class = c("tbl_df", "tbl", "data.frame"), 
              row.names = c(NA, -132L))

Answer:

Probably this is a bug in ggplotly. A solution is to use scales="free" inside facet_wrap and then to manually define the common x axes for the 4 plots.

p <- data %>%
  filter(!is.na(result)) %>%
  ggplot(aes(date_time, result)) +
  facet_wrap(~group, scales = "free") +
  geom_point() +
  geom_line()

g <- plotly_build(p)
# Set "x3" axis as common x-axis of Plot 1 and 3 
g$x$data[[1]]$xaxis <- "x3"
# Set "x4" axis as common x-axis of Plot 2 and 4
g$x$data[[2]]$xaxis <- "x4"
print(g)

Other solutions are here and here.

Question:

I do have a problem with plotly package. The legend does not display correctly or does not show all the values cause it is cut!

I would like to get the legend outside of the plot area (at the bottom or right corner).

I have already tried to change the position in ggplot:

legend.position="bottom"

no result at all...

then i have tried code from plotly website:

p %>% layout(legend = list(x = 0.5, y = -100))

it did not work, the legend was at the bottom, but it was cut, and behind x axis title...

Here is a sample code from mtcars dataset:

a <- ggplot(mtcars, aes(x = interaction(cyl, carb, lex.order = T), y = mpg,fill = interaction(cyl, carb, lex.order = T))) + 
  geom_boxplot()

ggplotly(a)

as we can see the title of the legend is cut there as well..

I would appreciate any help!

Thanks


Answer:

You could play with the margin and plot size. You can try:

m = list(
  l = 100,
  r = 40,
  b = 100,
  t = 50,
  pad = 0
)
a <- ggplot(mtcars, aes(x = interaction(cyl, carb, lex.order = T), y = mpg,fill = interaction(cyl, carb, lex.order = T))) + 
  geom_boxplot()
a %>% layout(autosize = F, width = 800, height = 600, margin = m)

Question:

I have the following dataset:

dput(head(active_clients))
structure(list(Date = structure(c(1422662400, 1425081600, 1427760000, 
1430352000, 1433030400, 1435622400), class = c("POSIXct", "POSIXt"
), tzone = "UTC"), value = c(65139, 66615, 66669, 67081, 67277, 
67366), month = 1:6, year = c(2015L, 2015L, 2015L, 2015L, 2015L, 
2015L), year_month = c("1/15", "2/15", "3/15", "4/15", "5/15", 
"6/15"), year2 = c("15", "15", "15", "15", "15", "15")), .Names = c("Date", 
"value", "month", "year", "year_month", "year2"), row.names = c(NA, 
-6L), class = c("tbl_df", "tbl", "data.frame"))

And i'm plotting the following line/point graph with ggplot2.

t <- ggplot(active_clients)  +
  geom_point(aes(as.factor(year_month), 
                 value), 
             size = 2, 
             color="deepskyblue4") +
  geom_line(aes(as.factor(year_month), 
                value,
                group = 1, alpha = 0.5), 
            color = "deepskyblue4") +

  xlab("") + 
  ylab("") +
  theme(legend.title = element_blank()) +
  theme_minimal()

ggplotly(t)

But I can't manage to remove the labels from the x - axis.

I've also tried adding:

theme(legend.title = element_blank(), axis.text = element_blank())

Not sure what I'm doing wrong.

Any hints?

Update

This is the plot I'm getting:


Answer:

To remove x-axis labels, you should try to use axis.text.x=element_blank() in the theme()

Removing the x-axis labels:

ggplot(active_clients)  +
  geom_point(aes(as.factor(year_month), value), size = 2, color="deepskyblue4") +
  geom_line(aes(as.factor(year_month), value, group = 1, alpha = 0.5), color = "deepskyblue4") +
  theme_minimal()+
  theme(axis.text.x=element_blank())

Question:

I am trying to use plotly for interactive visuals in my shiny app. However, I am running into a problem when trying to add a custom tooltip to the graph. If i set the tooltip argument in ggplotly() then my geom_line() is ignored in my output but the tooltip works.

Here is a MRE:

library(shiny)
library(ggplot2)
library(plotly)
library(tidyquant) #only using the palette_dark() function
library(magrittr)

graph <- data %>%
  ggplot(aes(date, result, text = paste0("Site: ", site, "\n", 
                                     "Quarter: ", quarter, "\n", 
                                     "Year: ", year, "\n", 
                                     "Result: ", result))) +
  facet_wrap(~site) +
  geom_point(color = palette_dark()[1]) +
  geom_line(color = palette_dark()[1]) +
  theme_bw() 

 ggplotly(graph, 
          tooltip = "text")

This gives me this:

If I move the data = and aes() calls from the ggplot call to the individual geoms then The lines still aren't shown:

graph <- ggplot() +
  facet_wrap(~site) +
  geom_point(data = data, 
             aes(date, result, 
                 text = paste0("Site: ", site, "\n", 
                               "Quarter: ", quarter, "\n",
                               "Year: ", year, "\n", 
                               "Result: ", result)),
             color = palette_dark()[1]) +
  geom_line(data = data, 
            aes(date, result, 
                text = paste0("Site: ", site, "\n", 
                              "Quarter: ", quarter, "\n",
                              "Year: ", year, "\n", 
                              "Result: ", result)),
            color = palette_dark()[1]) +
   theme_bw() 

ggplotly(graph, 
     tooltip = "text") 

This gives me the same output with the tooltips still working. However, now I receive two warnings:

Warning: Ignoring unknown aesthetics: text

Warning: Ignoring unknown aesthetics: text

If I remove the text= argument from just the geom_line() function then the lines are plotted but the tooltip no longer works:

Question:

How do I get the custom tooltip to work while still plotting my geom_line()?

My data:

data <- structure(list(site = c("Site 1", "Site 1", "Site 1", "Site 1", 
                                    "Site 2", "Site 2", "Site 2", "Site 2", 
                                    "Site 3", "Site 3", "Site 3", "Site 3", 
                                    "Site 4", "Site 4", "Site 4", "Site 4", 
                                    "Site 5", "Site 5", "Site 5", "Site 5"), 
                           parameter = c("Testing Parameter", "Testing Parameter",
                                         "Testing Parameter", "Testing Parameter", 
                                         "Testing Parameter", "Testing Parameter", 
                                         "Testing Parameter", "Testing Parameter", 
                                         "Testing Parameter", "Testing Parameter", 
                                         "Testing Parameter", "Testing Parameter", 
                                         "Testing Parameter", "Testing Parameter",
                                         "Testing Parameter",  "Testing Parameter", 
                                         "Testing Parameter", "Testing Parameter"),
                           year = c(2016, 2017, 2017, 2017, 2016, 2017, 2017, 2017, 
                                    2016, 2017, 2017, 2017, 2016, 2017, 2017, 2017, 
                                    2016, 2017, 2017, 2017), 
                           quarter = c(4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 
                                       3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L), 
                           result = c(22.87, 31.78, 54.76, 44.3, 27.78, 34.04, 53.27, 
                                      46.83, 19.83, 34.05, 31.18, 35.7,  24.11, 33.57, 
                                      47.5, 40.53, 29.4, 34.6, 53.18, 46.16), 
                           count = c(3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
                                     3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), 
                           date = structure(c(17075, 17167, 17257, 17348, 17075, 
                                              17167, 17257, 17348, 17075, 17167, 
                                              17257, 17348, 17075, 17167,  17257, 
                                              17348, 17075, 17167, 17257, 17348), 
                                            class = "Date")), 
                      class = c("tbl_df", "tbl", "data.frame"), 
                      row.names = c(NA, -20L), 
                      .Names = c("site", "parameter", "year", "quarter", "result", 
                                 "count", "date"))

Answer:

I think the lines weren't showing up because ggplot didn't know which points to connect together. I tried to plot the first graph (without converting to plotly object using ggplotly), & got the following warning:

> graph
geom_path: Each group consists of only one observation. Do you need to adjust the
group aesthetic?

Adding group = site to first set of code worked for me:

library(ggplot2); library(dplyr)

graph <- data %>%
  ggplot(aes(x = date, y = result, 
             text = paste0("Site: ", site, "\n", 
                           "Quarter: ", quarter, "\n", 
                           "Year: ", year, "\n", 
                           "Result: ", result),
             group = site)) +
  facet_wrap(~site) +
  geom_point() + # default palette since I don't have tidyquant
  geom_line() +
  theme_bw()

plotly::ggplotly(graph, tooltip = "text")

Question:

I am trying to make a graph with "time markers". These time markers are vertical lines for certain dates. Time data are POSIXct format. I would like to use the awesome interactive interface of Plotly and use my ggplot objects in it.

The problem is that these "time markers" doesn't show in after using ggplotly(). I ave already tried with plotly::add_segments() but it does not work. Here are two reproductible examples :

1. With non-POSIXct data it works fine

# dummy dataset
df2 = data.frame(id = 1:10, measure = runif(10, 0, 20))
events2 = data.frame(number = c(2,3,8))
# ggplot graph
p2 = ggplot() + geom_line(data = df2, aes(x = id, y = measure))  +
  geom_vline(data = events2, aes(xintercept = events2$number), color = "red")
p2
# plotly graph that displays the geom_vline properly
ggplotly(p2)

2. With POSIXct data is doesn't display the correct result

# dummy dataset
df = data.frame(date = seq(as.POSIXct("2017-07-01", tz = "UTC", format = "%Y-%m-%d"),
                           as.POSIXct("2018-04-15", tz = "UTC", format = "%Y-%m-%d"),
                           "1 month"),
                measure = runif(10, 0, 20))
events = data.frame(date_envents = as.POSIXct(c("2017-10-12", "2017-11-12", "2018-03-15"), tz = "UTC", format = "%Y-%m-%d"))
# ggplot graph
p = ggplot() + geom_line(data = df, aes(x = date, y = measure))  +
  geom_vline(data = events, aes(xintercept = events$date), color = "red")
p
# plotly graph that does not display the geom_vline properly
ggplotly(p)

I have seen some workaround (like this one : Add vertical line to ggplotly plot) but it is "complicated". Is there a more simple way to solve this problem ?

I am using Windows 10 with R version 3.5.0, RStudio and the following packages : library(tidyverse) and library(plotly)


Answer:

A simple workaround is to set the xintecept of the geom_vline to numeric.

sample data

df = data.frame(date = seq(as.POSIXct("2017-07-01", tz = "UTC", format = "%Y-%m-%d"),
                           as.POSIXct("2018-04-15", tz = "UTC", format = "%Y-%m-%d"),
                           "1 month"),
                measure = runif(10, 0, 20))
events = data.frame(date_envents = as.POSIXct(c("2017-10-12", "2017-11-12", "2018-03-15"), tz = "UTC", format = "%Y-%m-%d"))

code

p = ggplot() + geom_line(data = df, aes(x = date, y = measure))  +
  geom_vline(data = events, aes(xintercept = as.numeric(events$date)), color = "red")

result

ggplotly(p)

Question:

I was wondering if there's a way to have a custom icon for plotly's pie chart instead of the usual pie division

As of now I'm displaying the gender information using a pie chart which looks as below:

I'm trying to make it look like the gender plot in the link below:

https://app.displayr.com/Dashboard?id=c1506180-fe64-4941-8d24-9ec4a54439af#page=3e133117-f3b2-488b-bc02-1c2619cf3914

The plotly code is as under:

plot_ly(genderselection, labels = ~Gender, values = ~Freq, type = 'pie') %>%
      layout(title = paste0("Gender Distribution of Patients from Boston"),
             xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
             yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
             legend=list(orientation='h'))

The genderselection dataframe:

  Gender Freq
     F   70
     M   65

If not using plotly is there any other library that can be used to display information using custom icons ?


Answer:

(1) Download the png file available here and save it in your working directory as man_woman.png (2) Run the following code:

library(png)
library(plotly)

genderselection <- read.table(text="
  Gender Freq
     F   70
     M   30
", header=T)
pcts <- round(prop.table(genderselection$Freq)*100)

# Load png file with man and woman
img <- readPNG("man_woman.png")
h <- dim(img)[1]
w <- dim(img)[2]

# Find the rows where feet starts and head ends
pos1 <- which(apply(img[,,1], 1, function(y) any(y==1)))
mn1 <- min(pos1)
mx1 <- max(pos1)
pospctM <- round((mx1-mn1)*pcts[2]/100+mn1)
pospctF <- round((mx1-mn1)*pcts[1]/100+mn1)

# Fill bodies with a different color according to percentages
imgmtx <- img[h:1,,1]
whitemtx <- (imgmtx==1)
colmtx <- matrix(rep(FALSE,h*w),nrow=h)
midpt <- round(w/2)-10
colmtx[mx1:pospctM,1:midpt] <- TRUE
colmtx[mx1:pospctF,(midpt+1):w] <- TRUE
imgmtx[whitemtx & colmtx] <- 0.5

# Plot matrix using heatmap and print text
labs <- c(paste0(pcts[2], "% Males"),paste0(pcts[1], "% Females"))
ax <- list(ticks='', showticklabels=FALSE, showgrid=FALSE, zeroline=FALSE)
p <- plot_ly(z = imgmtx, showscale=FALSE, type='heatmap', width = 500,  height = 500) %>%
     add_text(x = c(100,250), y = c(20,20), type='heatmap', mode="text",
        text=labs, showlegend=FALSE, textfont=list(size=20, color="#FFFFFF"), inherit=FALSE) %>%
     layout(xaxis = ax,  yaxis = ax)  
p

Question:

ggplotly removes the legend of a geom_line plot using ggplot.

See e.g. below:

library(plotly)    
g <- ggplot(iris)
g = g + geom_line(aes(x = Sepal.Length, y = Sepal.Width, color = Species), size = 0.05)
g # Here is a legend
(gg <- ggplotly(g)) # Legend has now been removed.

Any ideas how to get back the legend?

I am using plotly_2.0.19 and ggplot2_2.0.0.9000.


Answer:

For some reason ggplotly never adds a legend for geom_line. The documentation only has legends when points are also added. I suggest using transparent points as a work around.

{ ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  geom_line() +
  geom_point(alpha = 0) } %>%
  ggplotly()