Reputation: 1610
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
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
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)
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