Thorst
Thorst

Reputation: 1610

Adjusting location of text with ggplot and plotly

I am having trouble printing a plot from ggplot to plotly, and maintaining a good text position.

Data example:

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

#mock data
df1 <- data.frame( 
  Gruppering2     = factor(c("Erhverv Erhverv Salg","Erhverv Erhverv Salg","Erhverv Erhverv Salg")),
  periode    = factor(c("Denne maaned","Denne uge", "I gaard")),
  Answer_rate = c(0.01,0.4,0.7),
  SVL    = c(0.40,0.43,0.67),
  over_180     = c(0.5,0.7,0.3)  
)

#color 
plotCol <- c( rgb(44,121,91, maxColorValue = 255),  rgb(139,0,0, maxColorValue = 255),rgb(0,0,139, maxColorValue = 255)) 

#plot code
dfpct <- melt(df1[,c(2,3,4,5)], id.vars = "periode",
              measure.vars = c( "Answer_rate","SVL", "over_180"), 
              variable.name = "P", value.name = "value")
dfpct <- na.omit(dfpct)

pct <- ggplot(dfpct, aes(x = periode, y = value, fill = P, group = P, width = 0.6)) + 
  geom_bar(stat = "identity", position="dodge", colour = "black", width = 0.7, show.legend = FALSE) +
  labs(x = NULL, y = "Calls") +
  #ggtitle("Forecast Error") +
  theme_bw() +
  theme(panel.grid.major = element_blank(),
        plot.title = element_text(size = rel(1.2), face = "bold", vjust = 1.5),
        axis.title = element_text(face = "bold"),
        axis.text = element_text(),
        legend.position = "bottom",
        legend.direction = "vertical",
        legend.key.width = unit(2, "lines"),
        legend.key.height = unit(0.5, "lines"),
        legend.title = element_blank()) +
  geom_text(aes(label=paste(value*100,"%",sep="")), position = position_dodge(width=0.6), vjust = -0.5 ) +
  scale_fill_manual(values = plotCol)

pct # the is perfectly located above

ggplotly(pct, textposition = 'top center') # text crosses over the bars

As you can see - the ggplot works excellent - however when I convert to plotly, the text is moved. I've tried playing around with various settings in both ggplot and plotly, but no luck yet.

Upvotes: 3

Views: 3240

Answers (2)

Leonardo Regino
Leonardo Regino

Reputation: 31

I had the same issue, I solved it by adding a value to the y axis, but in order to avoid the scaling issue, I added a percentage of the minimum. You can adjust it depending upon your data itself. I hope it helps:

geom_text(aes(label=paste(value*100,"%",sep=""), y = value+0.1*min(value), position = position_dodge(width = 0.6))

Upvotes: 2

Vance Lopez
Vance Lopez

Reputation: 1358

Looks like vjust is not recognized but maybe on the roadmap. From GitHub:

# convert ggplot2::element_text() to plotly annotation
make_label <- function(txt = "", x, y, el = ggplot2::element_text(), ...) {
  if (is_blank(el) || is.null(txt) || nchar(txt) == 0 || length(txt) == 0) {
    return(NULL)
  }
  angle <- el$angle %||% 0
  list(list(
    text = txt,
    x = x,
    y = y,
    showarrow = FALSE,
    # TODO: hjust/vjust?
    ax = 0,
    ay = 0,
    font = text2font(el),
    xref = "paper",
    yref = "paper",
    textangle = -angle,
    ...
  ))
}

Easiest approach might be to assign the y value in geom_text, but you'll lose some scaling in the height.

pct <- ggplot(dfpct, aes(x = periode, y = value, fill = P, group = P, width = 0.6)) + 
  geom_bar(stat = "identity", position="dodge", colour = "black", width = 0.7, show.legend = FALSE) +
  labs(x = NULL, y = "Calls") +
  theme_bw() +
  theme(panel.grid.major = element_blank(),
        plot.title = element_text(size = rel(1.2), face = "bold", vjust = 1.5),
        axis.title = element_text(face = "bold"),
        axis.text = element_text(),
        legend.position = "bottom",
        legend.direction = "vertical",
        legend.key.width = unit(2, "lines"),
        legend.key.height = unit(0.5, "lines"),
        legend.title = element_blank()) +
  geom_text(aes(label=paste(value*100,"%",sep=""), y = value+0.01), position = position_dodge(width = 0.6)) +
  scale_fill_manual(values = plotCol)

ggplotly(pct)

enter image description here

Alternatively, if you know the dimensions of the final output, you could edit the components of a plotly_build object:

gg <- plotly_build(pct)
gg$data[[4]]$y <- gg$data[[4]]$y+0.006
gg$data[[5]]$y <- gg$data[[5]]$y+0.006
gg$data[[6]]$y <- gg$data[[6]]$y+0.006

Upvotes: 5

Related Questions