How to controll hovertemplate when using `text` as argument - r

I have a surface I want to display with plotly (it has to be a surface and not a 3D mesh because a 3D mesh is not appropiate so I must pass on a matrix not a data.frame).
For this I want to control the hoverinfo so it won't display the x, y, z coordinated but it does display x * y = ... and x + y = .... However I am encountering a problem with the hovertext argument. Which correctly displays the things I want but also displays the x, y, z coordinates. Also, I can't get "<extra></extra>" to work.
This is attempt so far:
library(plotly)
mat <- 0:10 %*% t(0:10)
plot_ly() |>
add_surface(z = ~mat,
hovertext = paste(
"X*Y:", mat,
"<br>X+Y: ", rep(0:10, each = 11) + rep(0:10, 11),
"<extra></extra>") |>
matrix(ncol = 11),
hovertemplate = text)
I would like to know:
How can I remove the x, y, z coordinates from the hovertemplate?
How can I use "<extra></extra>" argument when using hovertemplate = text?
EDIT: Following #Kat's comment I edited this post to reflect what I learned. Thanks Kat!
Thank you for your help!

Instead of text, use hovertext.
library(plotly)
mat <- 0:10 %*% t(0:10)
plot_ly() |>
add_surface(z = ~mat,
hovertext = mat, # hovertext to use in the template
hovertemplate = paste0("X: %{x}<br>Y: %{y}<br>",
"Z: %{z}<br>Whatever: %{hovertext}",
"<extra></extra>"))

Related

Display maximum and minimum values of data points in Boxplot in plotly R

How can I display the values of minimum and maximum data points as text in boxplot which is plotted using plotly in R? Below is the sample reference to the code:
plot_ly(x = ~rnorm(50), type = "box") %>% add_trace(x = ~rnorm(50, 1))
You have to "switch" on the direction of the boxplot (min, max, median, q1, q3), as you plot horizontal boxplots.
plot_ly(x = ~rnorm(50), type = "box"
#-------------- set direction / switch on
, hoverinfo = "x") %>% # let plotly know that x-direction give the hoverinfo
#----------------------------------------
add_trace(x = ~rnorm(50, 1)) %>%
#---------------- format label - here show only 2 digits
layout(xaxis = list(hoverformat = ".2f")) # again define for x-axis/direction!
amendment based on comment: add annotation
Plotly supports to add text as a trace(i.e. add_text()) or as a layout option (i.e. annotations=list(...)).
The annotation option provides support for offset, pointer arrow, etc.
Thus, I picked this option.
To be able to access the minimum and maximum values, I pull out the vector data definition. The labels combine the terms min and max with a 2-digit rounded value. Adapt this to your liking and possibly outside the plot. You can define vectors that you supply to the options of the annotation = list(...) call. Just pay attention to the sequence of the elements in the vector.
set.seed(1234)
x1 <- rnorm(50)
x2 <- rnorm(50, 1)
plot_ly(type = 'box', hoverinfo = "x") %>%
add_trace(x = x1) %>%
add_trace(x = x2) %>%
layout(title = 'Box Plot',
annotations = list(
#------------- (x,y)-position vectors for the text annotation
y = c(0,1), # horizontal boxplots, thus 0:= trace1 and 1:= trace2
x = c( min(x1), min(x2) # first 2 elements reflect minimum values
,max(x1), max(x2) # ditto for maximum values
),
#------------- text label vector - simple paste of label & value
text = c( paste0("min: ", round(min(x1),2)), paste0("min: ", round(min(x2),2))
,paste0("max: ", round(max(x1),2)), paste0("max: ", round(max(x2),2))
),
#-------------- you can use a pointer arrow
showarrow = TRUE
#-------------- there are other placement options, check documentation for this
)
)

R Plotly -Stacked Barchart with total amount of bars text

Problem: I have a stacked barchart. Above each of the stacked bars I want to have a total number (i.e. the sum of the two bars - here: total). I tried to take usage of add_text but it did not work out as expected. Any suggestions what to change?
Remark: I do not want to cast the data.table object. The target frame on which the visualizations shall be made is new_frame.
Many thanks
library(data.table)
library(plotly)
Animals <- c("giraffes", "orangutans", "monkeys")
SF_Zoo <- c(20, 14, 23)
LA_Zoo <- c(12, 18, 29)
data <- data.table(Animals, SF_Zoo, LA_Zoo)
new_frame <- data.table::melt(data, id.vars='Animals')
new_frame[, total := sum(value), by = Animals]
plot_ly(new_frame, x = ~Animals,
y = ~value,
type = 'bar',
name = ~variable,
hoverinfo = "text",
text = ~paste(variable, value, total)) %>%
## Not working
add_text(x = ~Animals, y = ~value,
text = ~total, textposition = "top center") %>%
layout(yaxis = list(title = 'Count'), barmode = 'stack')
Plotly is a powerful package and I feel with you ... some of the logic is not always self-evident. In particular when adding hovertexts, text elements, and/or annotations. You have to be careful about what are your variables and what is the textual element you want to add/control.
I hope the following allows you to step through the in-and-outs.
(I) Hovertext
With your data.table you have a data.frame that you provide to a trace (think broadly of a geom in ggplot). In this case a "bar" trace. I changed a bit the code to make this clearer by pulling the dataframe out and only use an empty plot_ly() call and adding deliberately a "bar"-trace.
This is strictly not necessary. However it allows you to understand what you are working on.
new_frame %>%
plot_ly() %>%
add_bars(x = ~Animals,
y = ~value,
type = 'bar',
name = ~variable,
hovertemplate = "my value: %{y}"
) %>%
## Not working
# add_text(x = ~Animals, y = ~value,
# text = "gotcha", textposition = "top center") %>%
layout(yaxis = list(title = 'Count'), barmode = 'stack')
With this code you have altered the presentation of the "hover" tooltip. The name parameter controls the "title" of the tooltip. For example, hovering over the plot shows the formatted hover, i.e. "my value: " and the name of the stacked bar "SF_Zoo". In the template definition you refer to the y-variable and not your dataframe (column) variable (name).
(II) Adding a "text"
Again think geom_text with adding a "text" trace. Note that trace is not fully correct here. You then map the position of the text to the x and y parameter of add_text() call.
This will display a text fragment at each mapped position (x,y). In the example, I provide a text vector of the same length than (x,y) combinations. If you provide a single string, this will be replicated. Here the text trace inherits from your new_frame. Note you could provide a new object here similar to what is defined in the next step.
(III) adding annotations
With add_annotations() you can add text elements and pointers. Again, you can provide a new object. As we only need the 3 totals for the group of animals, I reduce the data for this step to what is needed. With this "data format" I can now supply the variable total to the text parameter. I set showarrow = TRUE to provide an example on how to augment the text add on with an arrow.
new_frame %>%
plot_ly() %>%
add_bars(x = ~Animals,
y = ~value,
type = 'bar',
name = ~variable,
hovertemplate = "my value: %{y}"
) %>%
## Now let's add a text trace (think ggplot layer)
add_text( x = ~Animals
,y = ~value,
,text = c("one","two","three","four","five","six") # this overwrites your values with a string
,textposition = "center"
) %>%
## add annotation
add_annotations(data = new_frame %>% select(Animals, total) %>% unique()
,x = ~Animals
,y = ~total
,text = ~total
## remove arrow and offset
,showarrow = TRUE
## with showarrow = TRUE you can control the arrow
# , ax = 20
# , ay = 40
) %>%
## control the layout of the chart
layout(yaxis = list(title = 'Count'), barmode = 'stack')
Feel free to explore further options.
In summary, in plotly you provide a vector of values to x, y, or text. Strictly speaking these do not need to be organised as a dataframe. The dataframe allows you to make use of the ~notation for variables. There are 2 ways to add text. Make sure to understand how you use the position mapping (x, y) in combination with the text. For purists add_annotation() is more in line with a ggplot mind to have arbitrary text. But by defining the data object you supply to add_text() you can achieve a similar result. add_annotations() give you some additional styling elements with various arrow-designs.

R Plotly rotation of text in add_text

I can't seem to get the text to rotate in Plotly, in a scatter plot, using add_text().
I'm just trying to get the same result that the angle argument yields in ggplot. In plotly, the output needs to have the hovertext if that's of consequence.
Example -
library(dplyr)
library(plotly)
data <- data.frame(
x = 1:10,
y = runif(10,0,10),
lab = LETTERS[1:10]
)
# base output needed in ggplot
p <- data %>%
ggplot(aes(x,y)) +
geom_text(aes(label = lab, angle = 90))
# doesn't respect angle arg - not that I'm looking to use ggplotly
ggplotly(p)
# plotly version
plot_ly(data) %>%
add_text(
x = ~x,
y = ~y,
text = ~lab,
hovertext = ~paste0("Label is ", lab),
# things I've tried (generally one at a time..)
textfont = list(angle = 90, textangle = 90, orientation = 90, rotate = 90)
)
I'm sure I'm missing something obvious, but I can't track it down.. Help pls!
It appears the solution is to use add_annotations() rather than add_text(). A textangle arg is then accpeted.
Edit - turns out you need two traces - annotations to achieve the text rotation, then markers for the hovertext. Setting opacity = 0 for the markers seems OK.

Adding arrow segments to a scatter plot in plotly

I have XY data I want to plot in a scatter plot using R's plotly package.
For some of the points I have arrows, defined by their X and Y start and end coordinates, which I also want to plot.
Here are the data:
set.seed(1)
df <- data.frame(x=rnorm(100),y=rnorm(100),
arrow.x.start=NA,arrow.y.start=NA,
arrow.x.end=NA,arrow.y.end=NA)
arrow.idx <- sample(100,20,replace = F)
df$arrow.x.start[arrow.idx] <- df$x[arrow.idx]
df$arrow.x.end[arrow.idx] <- df$arrow.x.start[arrow.idx]+runif(length(arrow.idx),-0.5,0.5)
df$arrow.y.start[arrow.idx] <- df$y[arrow.idx]
df$arrow.y.end[arrow.idx] <- df$arrow.y.start[arrow.idx]+runif(length(arrow.idx),-0.5,0.5)
Using ggplot2 this is achieved using:
library(ggplot2)
ggplot(df,aes(x=x,y=y))+geom_point()+theme_minimal()+
geom_segment(aes(x=arrow.x.start,y=arrow.y.start,xend=arrow.x.end,yend=arrow.y.end),arrow=arrow())
Which gives:
In plotly this will plot the points:
plotly::plot_ly(marker=list(size=5,color="black"),type='scatter',mode="markers",x=df$x,y=df$y,showlegend=F) %>%
plotly::layout(xaxis=list(title="x",zeroline=F,showticklabels=F,showgrid=F,showgrid=F),yaxis=list(title="y",zeroline=F,showticklabels=F,showgrid=F,showgrid=F))
So I'm trying to figure out how to add the arrows.
The add_segments has the x, xend, y, and yend arguments and adding that:
plotly::plot_ly(marker=list(size=5,color="black"),type='scatter',mode="markers",x=df$x,y=df$y,showlegend=F) %>%
plotly::layout(xaxis=list(title="x",zeroline=F,showticklabels=F,showgrid=F,showgrid=F),yaxis=list(title="y",zeroline=F,showticklabels=F,showgrid=F,showgrid=F)) %>%
plotly::add_segments(x=df$arrow.x.start,xend=df$arrow.x.end,y=df$arrow.y.start,yend=df$arrow.y.end,line=list(color="blue"))
Seems to add a point at the end of the line:
And I couldn't find in its documentation an argument that will add arrow head at the end of the line.
Any idea?
You can use annotations
plot_ly(df) %>%
add_markers(~x, ~y) %>%
add_annotations( x = ~arrow.x.end,
y = ~arrow.y.end,
xref = "x", yref = "y",
axref = "x", ayref = "y",
text = "",
showarrow = T,
ax = ~arrow.x.start,
ay = ~arrow.y.start,
data = df[!is.na(df$arrow.x.start),])

Writing the symbol degrees celsius in axis titles with R/plotly

I'm trying to write the symbol degrees celsius with R/Plotly in one of my titles. It works when I just use a simple plot a below:
# Working code
library(latex2exp)
set.seed(1)
betas <- rnorm(1000)
hist(betas, main = TeX("Temperature (^0C)"))
However, when I try to run the code through plotly, I get the following error: "unimplemented type 'expression' in 'HashTableSetup'".
#Initialise the plot
p <- plot_ly()
#Add axis names
#Font
f <- list(
family = "Courier New, monospace",
size = 18,
color = "#7f7f7f")
#X axis name
x <- list(
title = "x Axis",
titlefont = f)
#Y Axis name
y <- list(
title = TeX("Temperature (^0C)"),
titlefont = f)
#Add layout
p <- p %>%
layout(xaxis = x, yaxis= y)
p
Any ideas?
Try,
title = "Temperature (\u00B0C)"
Try title = expression("Temperature ("*~degree*C*")") or title = "Temperature (°C)"
I just found a hacky solution: Look for the special character on google and copy and paste it directly in the R code.
#Y Axis name
y <- list(
title = "Temperature (°C)",
titlefont = f)
I'm still interested in a less hacky solution which allows to insert LaTeX into Plotly.

Resources