5

I am using plotly with Rshiny to create a scatter plot with text labels. Below is a reproducible example:

library(ggplot2)
library(plotly)
dat <- data.frame(LongExpressionValue = rnorm(1:100), 
                  LongMethylationValue = rnorm(1:100), 
                  LongCopyNumberValue = rnorm(1:100))

rownames(dat) <- paste0('n',seq(1:100))

# ggplot
p <- ggplot(data = dat, aes(x = LongExpressionValue, y = LongMethylationValue)) + 
  geom_point(size = 2) + geom_smooth(method = lm) +
  geom_text(aes(label = rownames(dat)), vjust=-1.5, size = 3)

# ggplotly
ggplotly(p)

This creates a plot like:

enter image description here

How do I adjust my geom_text options so that the labels appear above and not overlapping the points? I do want to retain my ggplot code for it to be used across applications.

Thanks!

Komal Rathi
  • 4,164
  • 13
  • 60
  • 98
  • Is it necessary to use `ggplot2` and not call `plot_ly` directly? I find the solutions for those to be much easier, configs are all just lists of lists etc.. Specifically, the reference page on plotly's site allows positioning of all parts, and the hoverinfo and text options are amazing – Shape May 16 '16 at 19:23
  • What if you want to use `aes_string` instead of `aes`? – Komal Rathi May 16 '16 at 19:38
  • I usually just use `as.name` if I need to work with programmatically-generated plots – Shape May 16 '16 at 19:41
  • That's not working for me. Plus, I do want to retain my code in ggplot2 for it to be used across applications. Thanks though. – Komal Rathi May 16 '16 at 19:56

3 Answers3

3

Try this:

plot_ly(
    data = dat, 
    x = ~LongExpressionValue, 
    y = ~LongMethylationValue, 
    text = rownames(dat), 
    marker = list(size = 10), 
    mode = "markers+text",
    textposition = 'top center'
)

it's not worth working too hard at ggplot2 when you can go directly to the source. this is invaluable: https://plot.ly/r/reference/

Everything in plot_ly or in layout is a list of lists, so you can set your parameters easily (notice marker = list(size = 10))

EDIT: A slightly more complicated one showing the power of hoverinfo + text together:

plot_ly(
    data = dat, 
    x = ~LongExpressionValue, 
    y = ~LongMethylationValue, 
    text = paste0(rownames(dat), 
                      '<br>A:', 1:nrow(dat), #Examples of additional text
                      '<br>B:', sample(nrow(dat))), #Examples of additional text
        hoverinfo = 'text+x+y',
        marker = list(size = 10), 
        mode = "markers+text",
        textposition = 'top right')
Shape
  • 2,892
  • 19
  • 31
  • 1
    Oh alright I'll give that a try. I just had all my code in ggplot2 so thought it'd be easier if I added the function ggplotly() to convert my existing plots to plotly. – Komal Rathi May 16 '16 at 19:35
  • If you don't have to show the text on top, and would prefer it to be part of the hover-over, I recommend, removing the "+text" from the mode – Shape May 16 '16 at 19:44
1

If you want to stick with ggplot2 and keep your smooth line, you could increase slightly the size of your point and add your label inside each point:

p <- ggplot(data = dat, aes(x = LongExpressionValue, y = LongMethylationValue)) + 
  geom_point(size = 7) + geom_smooth(method = lm) +
  geom_text(aes(label = rownames(dat)), size = 2, color="white")

# ggplotly
ggplotly(p)

enter image description here

MLavoie
  • 9,671
  • 41
  • 36
  • 56
  • Unfortunately that doesn't work when you have long variable names. For instance instead of n1 I could have thisismylongvariablename. And it wouldn't fit in the circle. – Komal Rathi May 16 '16 at 20:02
1

If you would like to stay in ggplot2 you have to append a textposition element to the plotly_build list. textposition is missing in the original plotly_build even if hjust and vjust options are set.

So this works:

#devtools::install_github("ropensci/plotly") # if not already done
library(ggplot2)
library(plotly) 
dat <- data.frame(LongExpressionValue = rnorm(1:100),
              LongMethylationValue = rnorm(1:100),
              LongCopyNumberValue = rnorm(1:100))

rownames(dat) <- paste0('n',seq(1:100))  

gg <- ggplot(data = dat, aes(x = LongExpressionValue, y =LongMethylationValue)) + 
geom_point(size = 1) +
geom_smooth(method = lm) +
geom_text(aes(label = rownames(dat)), size = 3)

p <- plotly_build(gg)

length<-length(p$x$data)
invisible(lapply(1:length, function(x) p$x$data[[x]]<<-c(p$x$data[[x]], textposition ='top center')))

p

Georg
  • 61
  • 1
  • 8