How to add line breaks to plotly hover labels - r

Is there a way to get plotly to display the hover text on multiple lines/get it to recognize special characters line '\n' in the text?
A dummy version of what I'm looking to do is:
data <- data.frame(cbind(rnorm(10, 8), rnorm(10, 2)))
names(data)<-c("thing1", "thing2")
data$hovertext <- paste("here's a coordinate: ",
round(data$thing1,1), sep = "\n")
p <- plot_ly(data, type = 'scatter', x = thing1, y = thing2,
text = hovertext, hoverinfo = 'text', mode = "markers")
Which of course just ignores the separator and prints all on one line. Can I trick plotly/R into recognizing that line break?

Just use the HTML tag <br>:
library(plotly)
data <- data.frame(cbind(rnorm(10, 8), rnorm(10, 2)))
names(data) <- c("thing1", "thing2")
data$hovertext <- paste("here's a coordinate:",
round(data$thing1,1), sep = "<br>")
p <- plot_ly(data, type = 'scatter', x = ~thing1, y = ~thing2,
text = ~hovertext, hoverinfo = 'text', mode = "markers")
Additionally, you could use HTML tags to change the font styles as well (and much more)...

Related

Why is hovertemplate not showing up correctly for some data points for plotly in R

mydat2 <- data.frame(subject = c("math", "english", "chemistry"), score = c(80, 50, 65), class = c("A", "B", "A"), count = c(50, 60, 70))
library(plotly)
plot_ly(data = mydat2,
x = ~score,
y = ~count,
color = ~class,
customdata= ~class,
hoverinfo = 'text',
text = ~subject,
hovertemplate = paste(
"<b>%{text}</b><br><br>",
"%{yaxis.title.text}: %{y:,.0f}<br>",
"%{xaxis.title.text}: %{x:,.0f}<br>",
"Class: %{customdata}",
"<extra></extra>"
))
I'm confused as to why the hover for the left most point shows up as %{text} instead of english. The hover labels for the other 2 points on the plot are perfectly fine.
Here is your graph, with the hover template that you're looking for. The explanation follows.
plot_ly(data = mydat2,
x = ~score,
y = ~count,
color = ~class,
type = "scatter",
mode = "markers",
customdata= ~class,
hoverinfo = 'text',
text = ~I(subject), # <---- I changed!!
hovertemplate = paste(
"<b>%{text}</b><br><br>",
"%{yaxis.title.text}: %{y:,.0f}<br>",
"%{xaxis.title.text}: %{x:,.0f}<br>",
"Class: %{customdata}",
"<extra></extra>"
))
I've seen this problem before. I've usually come up with a workaround, but never really figured out what went wrong until now. I found a closed ticket on GitHub for this issue (closed in 2019). (Ah, ya... so not fixed.) Apparently, it has to do with using color.
However, the bright spot...for a hot minute someone actually believed it was a problem and came up with a fix. #cpsievert wrote a bit of code that includes an lapply call (towards the middle of the page, if you visit the site). When I investigated what the code did, I realized it could be a lot simpler (and it was pretty simple, to begin with).
That ticket on GitHub is here if you wanted to check that out.
This is the code the maintainer provided (that you don't actually need).
l <- plotly_build(p)$x
l$data <- lapply(l$data, function(tr) { tr[["text"]] <- I(tr[["text"]]); tr })
as_widget(l)
The fix is the function I(). Instead of hovertext = or text = ~subject, you need hovertext = or text = ~I(subject). <-- note the I()

Can’t display error bars with Plotly and Shiny

I’m trying to display error bars on a scatter plot with Shiny and plotly. Here’s my code in my server.R file:
data = reactiveVal()
observe({
results <- data.frame() # actually getting the data from here
# formatting output
final.results <- cbind(
"id" = paste(results$a,
results$b,
results$c,
sep = '-'),
"sigma" = sprintf("%.5g", results$s),
"c-e" = sprintf("%.3g",results$calc - results$exp)
)
data(final.results)
})
output$plot <- renderPlotly(
as.data.frame(data()[,c("id", "c-e", "sigma")]) %>% plot_ly(
x = ~`c-e`,
y = ~id,
height = 800,
type = 'scatter',
mode = 'markers',
marker = list(color = "#90AFD9"),
error_x = list(array = ~sigma, color = "#000000", type = "data")
)
)
The plot is ok except it’s not showing the error bars, what’s my mistake ?
EDIT: clarification for the origin of the data() function and what it’s return value is.
Thesprintf() function returns a character string, not a number, that is why it is not displaying the sigma values as error bars. If you want to keep 5 decimal places, use the round() function instead:
"sigma" = round(results$s, digits = 5)

Cannot display the text in plotly with R if there is only one data point

The code blow generates a plotly graph with one data point. I design this plot to be able to display some text information when the users move the mouse cursor to the data point, but as the plot shows, this does not work.
library(dplyr)
library(lubridate)
library(plotly)
a1 <- data.frame(
DateTime = ymd_hms("2020-01-01 08:00:00"),
Value = 1
)
a1 <- a1 %>%
mutate(DateTimeText = as.character(DateTime))
p1 <- plot_ly(a1, x = ~DateTime, y = ~Value, type = "scatter", mode = "markers",
text = ~DateTimeText,
hovertemplate = paste(
"<br>Date Time: %{text} </br>",
"<br>Value: %{y} </br>",
"<extra></extra>"))
However, if I provided two data points. The code works. Here is an example. This is strange to me as I think both cases should work. Please give some advice.
a2 <- data.frame(
DateTime = ymd_hms(c("2020-01-01 08:00:00", "2020-01-02 08:00:00")),
Value = c(1, 2)
)
a2 <- a2 %>%
mutate(DateTimeText = as.character(DateTime))
p2 <- plot_ly(a2, x = ~DateTime, y = ~Value, type = "scatter", mode = "markers",
text = ~DateTimeText,
hovertemplate = paste(
"<br>Date Time: %{text} </br>",
"<br>Value: %{y} </br>",
"<extra></extra>"))
The issue is that your length 1 vector in R is not properly converted to a JSON array of length 1. This a known pitfall as there is some ambiguity when converting R objects to JSON, see https://plotly-r.com/json.html. This ambiguity does not arise when you have a vector of length > 1. That's why you code works in such cases.
To solve this make use of the asIs function or I, i.e. use text = ~I(DateTimeText). Try this:
library(dplyr)
library(lubridate)
library(plotly)
a1 <- data.frame(
DateTime = ymd_hms("2020-01-01 08:00:00"),
Value = 1
)
a1 <- a1 %>%
mutate(DateTimeText = as.character(DateTime))
p1 <- plot_ly(a1, x = ~DateTime, y = ~Value, type = "scatter", mode = "markers",
text = ~I(DateTimeText),
hovertemplate = paste(
"<br>Date Time: %{text} </br>",
"<br>Value: %{y} </br>",
"<extra></extra>"))
p1

R Shiny XTS - Change name of the default tooltip using ggplot

I have a xts object that has dates as values, I'm using ggplot2 and shiny app for show the result.
But I want to change the default names of the tooltip when the mouse is on the line.
From:
index: 2020-03-19
value: 70
To:
Date: 2020-03-19
Cantidad: 70
Code for XTS:
data<-rnorm(10)
dates <- seq(as.Date("2016-01-01"), length =10, by = "days")
xtsMyData <- xts(x = data, order.by = dates)
Plot:
r <- ggplot(tidy(xtsMyData), aes(x=index,y=value, color=series, type = 'scatter', mode = 'lines')
) + geom_line(size=2)
The result is:
I'm triyng the following code:
r <- ggplot(tidy(xtsMyData), aes(x=index,y=value, color=series, type = 'scatter', mode = 'lines')
) + geom_line(size=2)
return(ggplotly(r, tooltip = **c("x","y", "series" )**) %>% plotly::config(displayModeBar = T) %>%
layout(legend = list(orientation = "h", x = 0.4, y = -0.2)))
And the result is:
How can I change the tooltip? Can I add words? I tried with paste("Dates","x") but doesn't work.
Thanks for your help.
You can use text in style to change the hover text.
The plotly object will have values accessible through a list as below. The date values will need to be converted with as.Date.
Edit: The code includes a full shiny app as a demo.
library(xts)
library(shiny)
data<-rnorm(10)
dates <- seq(as.Date("2016-01-01"), length =10, by = "days")
xtsMyData <- xts(x = data, order.by = dates)
ui <- fluidPage(
plotlyOutput("myplot")
)
server <- function(input, output, session) {
output$myplot <- renderPlotly({
r <- ggplot(tidy(xtsMyData), aes(x=index,y=value, color=series, type = 'scatter', mode = 'lines')) +
geom_line(size=2)
r <- ggplotly(r) %>%
plotly::config(displayModeBar = T) %>%
layout(legend = list(orientation = "h", x = 0.4, y = -0.2))
r %>%
style(text = paste0("Date:", as.Date(r$x$data[[1]]$x),
"</br></br>",
"Cantidad:", r$x$data[[1]]$y))
})
}
shinyApp(ui, server)
Plot
The first answer gave me the idea to change manually all, because I had 2 different geom_lines and that didn't work for me , this labels are stored in r$x$data[[1]]$text (the following line plots are in r$x$data[[2]]$text,r$x$data[[3]]$text... ), so, if you use an gsub, you could change everything you want, it's very dumb but it works. (You can use the same philosophy to delete the last label, manipulating strings)
I put an example for your problem, despite you already solve it, other person could have more than one line plot.
r$x$data[[1]]$text<-gsub(r$x$data[[1]]$text,pattern='index', replacement='Fecha')
r$x$data[[1]]$text<-gsub(r$x$data[[1]]$text,pattern='value', replacement='Valor')
r$x$data[[1]]$text<-gsub(r$x$data[[1]]$text,pattern='series', replacement='Serie')

Plotly: text is overwritten when traces are added using for loops

I have created a plotly scatter plot which I add traces to using a for loop. When I add text labels or hoverinfo, the text for the last point overwrites all others. Does anyone know how to prevent this?
I have created a reproducible example below where the (correctly named) blue points are created outside the loop however the red points created within the loop have their names overwritten (all incorrectly labelled E as opposed to A->E):
library(plotly)
data.frame1 <- data.frame("name"=paste("name", LETTERS[6:10]), "x"=-1:-5, "y"=-1:-5)
data.frame2 <- data.frame("name"=paste("name", LETTERS[1:5]), "x"=1:5, "y"=1:5)
p <- plot_ly(data.frame1, x = ~x, y = ~y, text = ~paste0(name),
name = "Outside loop", type ="scatter",
mode = "markers+text", marker=list(color="blue") )
for(i in 1:nrow(data.frame2)) {
point <- data.frame2[i, ]
p <- p %>% add_trace(x = point$x, y = point$y, text = ~paste0(point$name),
type ="scatter", mode = "markers+text",
marker = list(color="red", size=10),
name=point$name )
}
p
The ~ sign causes the problem, remove in the loop and it should be fine. It makes sense when you refer to your data frame like in the first example but it causes the weird behavior you are observing in the loop.
library(plotly)
data.frame1 <- data.frame("name"=paste("name", LETTERS[6:10]), "x"=-1:-5, "y"=-1:-5)
data.frame2 <- data.frame("name"=paste("name", LETTERS[1:5]), "x"=1:5, "y"=1:5)
p <- plot_ly(data.frame1, x = ~x, y = ~y, text = ~paste0(name),
name = "Outside loop", type ="scatter",
mode = "markers+text", marker=list(color="blue") )
for(i in 1:nrow(data.frame2)) {
point <- data.frame2[i, ]
print(paste0(point$name))
p <- p %>% add_trace(x = point$x, y = point$y, text = paste0(point$name),
type ="scatter", mode = "markers+text",
marker = list(color="red", size=10),
name=point$name )
}
p

Resources