How to add text to a plotly boxplot in r - r

I would like to mark the outlier that appears on my chart writing where it is. Is this possible with plotly?
The code of my graph is here:
library(plotly)
set.seed(1234)
plot_ly(y = rnorm(50), type = 'box') %>%
add_trace(y = rnorm(50, 1)) %>%
layout(title = 'Box Plot',
xaxis = list(title = "cond", showgrid = F),
yaxis = list(title = "rating"))

It's not clear what you tried and what's not working, but one way to identify outliers is to use boxplot.stats() and then you can use that information to add annotations.
library(plotly)
set.seed(1234)
d <- rnorm(50)
d2 <- rnorm(50, 1)
plot_ly(y = d, type = 'box') %>%
add_trace(y = d2) %>%
layout(title = 'Box Plot',
xaxis = list(title = "cond", showgrid = F),
yaxis = list(title = "rating"),
annotations = list(
x = -0.01,
# use boxplot.stats() to get the outlier's y coordinate
y = boxplot.stats(d)$out,
text = "Outlier",
showarrow = FALSE,
xanchor = "right"
)
)

Related

Hover is not spot on in R plotly with hovermode 'x unified'

I created a graph with two traces in plotly and I use the hovermode x unified. At some point there is no data for line 2, but there is for line 1. In the hoover I only want to see the information about line 1 then, but it also shows information about the nearest point of line 2. When I zoom in the issue dissapears.
So in short, I want to disable the closest function of the hovermode. How can I do this?
Some sample data + code:
library(plotly)
# dummy data
df_data1 = data.frame(date_input = seq(as.Date('2020/01/01'), as.Date('2022/07/01'), by="week")
, value=1:131)
df_data2 = data.frame(date_input = seq(as.Date('2020/01/01'), as.Date('2022/06/01'), by="week")
, value2=3:129)
plot1 <- plot_ly()
plot1 <- plot1 %>%
add_trace(data = df_data1, x = ~date_input, y = ~value
, type = 'scatter', mode = "lines", yaxis = "y", line = list(color = '#E64B35FF', opacity = 0.8)
, showlegend = FALSE
, hovertemplate = ~paste('# Value1: %{y:.0f}<extra></extra>')) %>%
add_trace(data = df_data2, x = ~date_input, y = ~value2
, type = 'scatter', mode = "lines", yaxis = "y2", line = list(color = '#4DBBD5FF', opacity = 0.8)
, showlegend = FALSE
, hovertemplate = ~paste('# Value2: %{y:.0f}<extra></extra>'))
plot1 %>%
layout(
font = list(size = 10),
xaxis = list(title = list(text = '<b>Date<b>', font = list(size = 12))
, fixedrange = T, showgrid = FALSE, ticks = 'inside', type = 'date'
),
yaxis = list(title = list(text = '<b>Number of value1<b>', font = list(size = 12, color = '#E64B35FF'))
, fixedrange = T
, rangemode = 'tozero', showgrid = FALSE, showline = T, ticks = 'inside'),
yaxis2 = list(overlaying = 'y', side = 'right', fixedrange = T, rangemode = 'tozero', showgrid = FALSE, showline = T, ticks = 'inside'
, title = list(text = '<b>Number of value2<b>', font = list(size = 12, color = '#4DBBD5FF'))),
hovermode = "x unified"
)
As you can see the hovermode shows the value2 information still at 15 june (but it shows the closest data from 1 june.

I have added multiple labels for my vertical lines in my plotly graph and the points I specified for the label location is connected by a line?

This is the code I used for producing the graph:
plot1 <- plot_ly(ukdf, x = ~date, y = ~weeklyincidence,
name = "Weekly Incidence/100k",
type = "scatter",
mode = "lines+markers",
line = list(width = 2)) %>%
layout(title = "United Kingdom: Impact of Vaccination on ICU admissions", xaxis = list(title = "Date",
zerolinewidth = 2,
nticks = 20),
yaxis = list(title = "Weekly Incidence/100k & ICU admissions"),
autosize = F, width = 1500, height = 500)
plot1 <- plot1 %>% add_trace(y = ~severeicu,
name = "ICU admissions",
line = list(width = 2)) %>%
layout(shapes = list(vline(as.Date("2020-12-08")),
vline(as.Date("2021-06-09")),
vline(as.Date("2021-09-02")),
vline(as.Date("2021-12-19"))))
**plot1 %>%
add_text(showlegend = FALSE, x = c("2020-12-08", "2021-06-09", "2021-09-02", "2021-12-19"), y = c(4300, 2500, 3000, 4000),
text = c("Start of Vaccination", "50% fully vaccinated", "75% vaccinated", "50% boosted"),
mode = "markers"**)
print(plot1)
Plotly automatically adds a line between the add_text label positioning points that I have specified. How can I remove this line?

Plotly: dual y axis graph messing up line graph

I'm trying to make a dual axis plot of rainfall and temperature. I have ordered the months on the bottom, but that causes my line graph to screw up. How do I make sure the added line uses the same x axis?
temprain<-data.frame(month = c(1:12),
Train = c(250,220, 180,97,38,27,31,47,70,140,200,250),
Tair = c(17,16, 15,13,9,6,5,9,12,13,14,16))
tempseq<-seq(0,20,by=0.5)
rainseq<-seq(0,260,by=1)
xlab<-list(type = "category",
categoryorder = "array",
categoryarray = month.name,
showgrid = TRUE,
showline = TRUE,
autorange = TRUE,
showticklabels = TRUE,
ticks = "outside",
tickangle = 0
)
plot_ly(temprain) %>%
add_bars(x = ~MonthName, y = ~Train, type = "bar", name = "Rain") %>%
add_lines(x = ~MonthName, y = ~Tair, yaxis = "y2", name = "Temp") %>%
layout(xaxis = xlab,
yaxis = list(showline = TRUE, side = "left",
title = "Rainfall (mm)Temp", range = tempseq),
yaxis2 = list(showline = TRUE, side = "right",
overlaying = "y", title = "Air Temp (C)", range = rainseq),
showlegend = FALSE,
margin = list(pad = 0, b = 50, l = 50, r = 50))
I tried this as well, and it doesn't work, the temp graph disappears
plot_ly(temprain, x = ~MonthName, y = ~Tair, name = "Temp") %>%
add_bars(x = ~MonthName, y = ~Train, yaxis = "y2", type = "bar", name = "Rain") %>%
layout(xaxis = xlab,
yaxis = list(showline = TRUE, side = "left",
title = "Air Temp (C)", range = tempseq),
yaxis2 = list(showline = TRUE, side = "right",
overlaying = "y",
title = "Rainfall (mm)", range = rainseq),
showlegend = FALSE,
margin = list(pad = 0, b = 50, l = 50, r = 50))
Below is the solution:
Your data:
temprain<-data.frame(month = c(1:12),
Train = c(250,220, 180,97,38,27,31,47,70,140,200,250),
Tair = c(17,16, 15,13,9,6,5,9,12,13,14,16))
Generate a column for month abbreviations from month:
mymonths <- c("Jan","Feb","Mar",
"Apr","May","Jun",
"Jul","Aug","Sep",
"Oct","Nov","Dec")
# match the month numbers against abbreviations:
temprain$MonthAbb = mymonths[ temprain$month ]
# This is the code to archieving a consistent combined graph:
temprain$MonthAbb <- factor(temprain$MonthAbb, levels = c(as.character(temprain$MonthAbb)))
Now plot your data:
fig <- plot_ly(temprain)
# Add the Train trace:
fig <- fig %>% add_trace(x = ~MonthAbb, y = ~Train, name = "Train", type = "bar")
ay <- list(
tickfont = list(color = "red"),
overlaying = "y",
side = "right",
title = "<b>Tair</b>")
# Add the Tair trace:
fig <- fig %>% add_trace(x = ~MonthAbb, y = ~Tair, name = "Tair", yaxis = "y2", mode = "lines+markers", type = "scatter")
fig <- fig %>% layout(yaxis2 = ay,
xaxis = list(title="Month"),
yaxis = list(title="<b>Train</b>"))%>%
layout(xaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff'),
yaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff')
)
fig
Output:

Switch displayed traces via plotly dropdown menu

I am working with the R programming language. I am trying to replicate this tutorial over here for my own data: https://plotly.com/r/dropdowns/
I created some fake data and made 4 plots:
#load libraries
library(plotly)
library(MASS)
library(dplyr)
# create data
x <- sample( LETTERS[1:4], 731, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25) )
y <- rnorm(731,10,10)
z <- rnorm(731,5,5)
date= seq(as.Date("2014/1/1"), as.Date("2016/1/1"),by="day")
df <- data.frame(x,y, z, date)
df$x = as.factor(df$x)
# plot 1 : time series
aggregate = df %>%
mutate(date = as.Date(date)) %>%
group_by(month = format(date, "%Y-%m")) %>%
summarise( mean = mean(y))
ts_1 <- ggplot(aggregate) + geom_line(aes(x = month, y = mean, group = 1)) + theme(axis.text.x = element_text(angle = 90)) + ggtitle("time series 1")
plot_1 = ggplotly(ts_1)
#plot 2 : box plot
plot_2 <- plot_ly(df, y = ~y, color = ~x, type = "box") %>% layout(title = "boxplot")
#plot 3, 4 : scatter plots
df_1 <- df[which(df$x == "A"),]
df_2 <- df[which(df$x == "B"),]
plot_3 <- plot_ly( data = df_1, type = "scatter", mode = "markers", x = ~ y, y = ~z) %>% layout(title = "graph 3")
plot_4 <- plot_ly( data = df_2, type = "scatter", mode = "markers", x = ~ y, y = ~z) %>% layout(title = "graph 4")
Once these 4 plots have been created, I know how to save them together:
sub = subplot(plot_1, plot_2, plot_3, plot_4, nrows = 2)
#view result
sub
Now what I am trying to do, is have the user "toggle" (switch) between these graphs (as seen here: https://plotly.com/r/dropdowns/)
In a previous post (R: Switching Between Graphs ), I learned how to "glue" similar graphs together (e.g. 4 scatter plots). Now, I am trying to do so with different graphs (2 scatter plots, 1 time series and 1 box plot). I tried to adapt the code from the previous post to suit my example:
fig <- df %>%
add_trace(name = "A", plot_1) %>%
add_trace (name = "B" , df, y = ~y, color = ~x, type = "box") %>% layout(title = "boxplot")
add_trace (name = "C" , data = df_1, type = "scatter", mode = "markers", x = ~ y, y = ~z) %>% layout(title = "graph 3") %>%
add_trace( name = "D", data = df_2, type = "scatter", mode = "markers", x = ~ y, y = ~z) %>% layout(title = "graph 4") %>%
layout(xaxis = list(domain = c(0.1, 1)),
yaxis = list(title = "y"),
updatemenus = list(
list(
y = 0.7,
buttons = list(
list(method = "restyle",
args = list("visible", list(TRUE, FALSE, FALSE, FALSE)),
label = "A"),
list(method = "restyle",
args = list("visible", list(FALSE, TRUE, FALSE, FALSE)),
label = "B"),
list(method = "restyle",
args = list("visible", list(FALSE, FALSE, TRUE, FALSE)),
label = "C"),
list(method = "restyle",
args = list("visible", list(FALSE, FALSE, FALSE, TRUE)),
label = "D")))))
But this produces the following errors:
Error: $ operator is invalid for atomic vectors
Error in add_data(p, data) : argument "p" is missing, with no default
Can someone please show me if it is possible to fix this problem? Instead of using the "add_trace" approach, is it somehow possible to individually call each plotly graph object by its name (e.g. subplot(plot_1, plot_2, plot_3, plot_4, nrows = 2)), "glue" all the graphs together, and then add a "toggle button" that lets the user switch between them?
(note: I need to be able to save the final result as a "html" file)
Thanks
First of all, you should take care about plots which add multiple traces (see nTracesA etc.)
Besides changing the trace visibility you'll need to seperate categorial and numerical data onto separate x and y-axes and manage their visibility, too (see xaxis2, xaxis3, xaxis4 - this also works with a single y-axis but in this case the grid isn't displayed properly)
As described in the docs:
The updatemenu method determines which plotly.js function will be used
to modify the chart. There are 4 possible methods:
"restyle": modify data or data attributes
"relayout": modify layout attributes
"update": modify data and layout attributes
"animate": start or pause an animation (only available offline)
Accordingly the following, is using the update method (a lot of repition here - needs some cleanup, but I think it's better to understand this way):
# load libraries
library(dplyr)
library(plotly)
# create data
x <- sample(LETTERS[1:4],
731,
replace = TRUE,
prob = c(0.25, 0.25, 0.25, 0.25))
y <- rnorm(731, 10, 10)
z <- rnorm(731, 5, 5)
date <- seq(as.Date("2014/1/1"), as.Date("2016/1/1"), by = "day")
df <- data.frame(x, y, z, date)
df$x = as.factor(df$x)
nTracesA <- nTracesC <- nTracesD <- 1
nTracesB <- length(unique(df$x))
plotA <- plot_ly(data = df %>%
mutate(date = as.Date(date)) %>%
group_by(month = format(date, "%Y-%m")) %>%
summarise(mean = mean(y)),
type = 'scatter', mode = 'lines', x= ~ month, y= ~ mean, name = "plotA", visible = TRUE, xaxis = "x", yaxis = "y")
plotAB <- add_trace(plotA, data = df, x = ~x, y = ~y, color = ~ x, name = ~ paste0("plotB_", x),
type = "box", xaxis = "x2", yaxis = "y2", visible = FALSE, inherit = FALSE)
plotABC <- add_trace(plotAB, data = df[which(df$x == "A"),],
type = "scatter", mode = "markers", x = ~ y, y = ~ z,
name = "plotC", xaxis = "x3", yaxis = "y3", visible = FALSE, inherit = FALSE)
plotABCD <- add_trace(plotABC, data = df[which(df$x == "B"),], x = ~ y, y = ~ z,
type = "scatter", mode = "markers", name = "plotD", xaxis = "x4", yaxis = "y4", visible = FALSE, inherit = FALSE)
fig <- layout(plotABCD, title = "Initial Title",
xaxis = list(domain = c(0.1, 1), visible = TRUE, type = "date"),
xaxis2 = list(overlaying = "x", visible = FALSE),
xaxis3 = list(overlaying = "x", visible = FALSE),
xaxis4 = list(overlaying = "x", visible = FALSE),
yaxis = list(title = "y"),
yaxis2 = list(overlaying = "y", visible = FALSE),
yaxis3 = list(overlaying = "y", visible = FALSE),
yaxis4 = list(overlaying = "y", visible = FALSE),
updatemenus = list(
list(
y = 0.7,
buttons = list(
list(label = "A",
method = "update",
args = list(list(name = paste0("new_trace_name_", 1:7), visible = unlist(Map(rep, x = c(TRUE, FALSE, FALSE, FALSE), each = c(nTracesA, nTracesB, nTracesC, nTracesD)))),
list(title = "title A",
xaxis = list(visible = TRUE),
xaxis2 = list(overlaying = "x", visible = FALSE),
xaxis3 = list(overlaying = "x", visible = FALSE),
xaxis4 = list(overlaying = "x", visible = FALSE),
yaxis = list(visible = TRUE),
yaxis2 = list(overlaying = "y", visible = FALSE),
yaxis3 = list(overlaying = "y", visible = FALSE),
yaxis4 = list(overlaying = "y", visible = FALSE)))
),
list(label = "B",
method = "update",
args = list(list(visible = unlist(Map(rep, x = c(FALSE, TRUE, FALSE, FALSE), each = c(nTracesA, nTracesB, nTracesC, nTracesD)))),
list(title = "title B",
xaxis = list(visible = FALSE),
xaxis2 = list(overlaying = "x", visible = TRUE),
xaxis3 = list(overlaying = "x", visible = FALSE),
xaxis4 = list(overlaying = "x", visible = FALSE),
yaxis = list(visible = FALSE),
yaxis2 = list(overlaying = "y", visible = TRUE),
yaxis3 = list(overlaying = "y", visible = FALSE),
yaxis4 = list(overlaying = "y", visible = FALSE)))),
list(label = "C",
method = "update",
args = list(list(visible = unlist(Map(rep, x = c(FALSE, FALSE, TRUE, FALSE), each = c(nTracesA, nTracesB, nTracesC, nTracesD)))),
list(title = "title C",
xaxis = list(visible = FALSE),
xaxis2 = list(overlaying = "x", visible = FALSE),
xaxis3 = list(overlaying = "x", visible = TRUE),
xaxis4 = list(overlaying = "x", visible = FALSE),
yaxis = list(visible = FALSE),
yaxis2 = list(overlaying = "y", visible = FALSE),
yaxis3 = list(overlaying = "y", visible = TRUE),
yaxis4 = list(overlaying = "y", visible = FALSE)))),
list(label = "D",
method = "update",
args = list(list(visible = unlist(Map(rep, x = c(FALSE, FALSE, FALSE, TRUE), each = c(nTracesA, nTracesB, nTracesC, nTracesD)))),
list(title = "title D",
xaxis = list(visible = FALSE),
xaxis2 = list(overlaying = "x", visible = FALSE),
xaxis3 = list(overlaying = "x", visible = FALSE),
xaxis4 = list(overlaying = "x", visible = TRUE),
yaxis = list(visible = FALSE),
yaxis2 = list(overlaying = "y", visible = FALSE),
yaxis3 = list(overlaying = "y", visible = FALSE),
yaxis4 = list(overlaying = "y", visible = TRUE))))
))))
print(fig)
# htmlwidgets::saveWidget(partial_bundle(fig), file = "fig.html", selfcontained = TRUE)
# utils::browseURL("fig.html")
Some related info:
https://plotly.com/r/custom-buttons/
https://plotly.com/r/multiple-axes/
This is just a guess from the documentation but there is no add_data() call so maybe try this for your first line:
fig <- plot_ly() %>% add_data(df) %>%
See docs example:
plot_ly() %>% add_data(economics) %>% add_trace(x = ~date, y = ~pce)
A user on the Rstudio community forum provided an answer : https://community.rstudio.com/t/gluing-graphs-together-switch-toggle-between-graphs-in-r-plotly/95891/3
I am still trying to figure out how to format the axis - maybe someone could take a look at this?
#load libraries
library(plotly)
library(MASS)
library(dplyr)
# create data
x <- sample( LETTERS[1:4], 731, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25) )
y <- rnorm(731,10,10)
z <- rnorm(731,5,5)
date= seq(as.Date("2014/1/1"), as.Date("2016/1/1"),by="day")
df <- data.frame(x,y, z, date)
df$x = as.factor(df$x)
# plot 1 : time series
aggregate = df %>%
mutate(date = as.Date(date)) %>%
group_by(month = format(date, "%Y-%m")) %>%
summarise( mean = mean(y))
ts_1 <- ggplot(aggregate) + geom_line(aes(x = month, y = mean, group = 1)) + theme(axis.text.x = element_text(angle = 90)) + ggtitle("time series 1")
plot_1 = ggplotly(ts_1)
#plot 2 : box plot
plot_2 <- plot_ly(df, y = ~y, color = ~x, type = "box") %>% layout(title = "boxplot")
#plot 3, 4 : scatter plots
df_1 <- df[which(df$x == "A"),]
df_2 <- df[which(df$x == "B"),]
plot_3 <- plot_ly( data = df_1, type = "scatter", mode = "markers", x = ~ y, y = ~z) %>% layout(title = "graph 3")
plot_4 <- plot_ly( data = df_2, type = "scatter", mode = "markers", x = ~ y, y = ~z) %>% layout(title = "graph 4")
fig = plot_ly()
fig = fig %>% add_trace(data = df %>%
mutate(date = as.Date(date)) %>%
group_by(month = format(date, "%Y-%m")) %>%
summarise( mean = mean(y)), type = 'scatter', mode = 'lines', x= ~month, y= ~mean,
name = "timeseries")
fig = fig %>% add_trace(data = df[which(df$x == "A"),], y = ~y, color = ~x,
type = "box", name = "boxplot")
fig = fig %>% add_trace( data = df[which(df$x == "B"),],
type = "scatter", mode = "markers", x = ~ y, y = ~z,
name= "graph2")
fig = fig %>% add_trace(data = df[which(df$x == "A"),], y = ~y, color = ~x,
type = "box", name = "boxplot2")
fig %>% layout(xaxis = list(domain = c(0.1, 1)),
yaxis = list(title = "y"),
updatemenus = list(
list(
y = 0.7,
buttons = list(
list(method = "restyle",
args = list("visible", list(TRUE, FALSE, FALSE, FALSE)),
label = "A"),
list(method = "restyle",
args = list("visible", list(FALSE, TRUE, FALSE, FALSE)),
label = "B"),
list(method = "restyle",
args = list("visible", list(FALSE, FALSE, TRUE, FALSE)),
label = "C"),
list(method = "restyle",
args = list("visible", list(FALSE, FALSE, FALSE, TRUE)),
label = "D")))))

How to add textbox on plot in plotly R?

I would like to add a text-box or information text on plot generated with plotly.
It seems like that now.
without text
I want to make it with text-box as follows (no need to circle:))).
with text-box
The code so far:
p <- plot_ly(data=data.mosann, x = ~Combined, y = ~Actual)%>%
layout(shapes=list(type='line', x0= 0, x1= 235, y0=0, y1=235, line=list(color='red',width=3)),
title = 'Scatter Plot Measurements-Combined Improvements MinT',
xaxis = list(title = "Combined MinT", showgrid = TRUE),
yaxis = list(title = "Measurements", showgrid = TRUE))
p
Try this. Change the x and y for layout annotation based on where you want your text.
p <- plot_ly(data=data.mosann, x = ~Combined, y = ~Actual)%>%
layout(xaxis = ~Combined, yaxis = ~Actual,
annotations = list(text = "YOUR TEXT HERE", x = 200, y = 30,showarrow=FALSE ),
shapes=list(type='line', x0= 0, x1= 235, y0=0, y1=235, line=list(color='red',width=3)),
title = 'Scatter Plot Measurements-Combined Improvements MinT',
xaxis = list(title = "Combined MinT", showgrid = TRUE),
yaxis = list(title = "Measurements", showgrid = TRUE))

Resources