Adding polygon to plotly scatterplot - r

I created a plotly scatterplot in R on which I would like to add a polygon.
current plot
This is the code I used to make the graph:
fig <- plot_ly(data = data, x= ~xbeak, y = ~ybeak, color = ~coordsbeak, text = ~paste(coordsbeak), type = 'scatter')
Now I want to add a polygon to this plot, which I tried with add_polygons. The polygon is a different dataframe, consisting two columns with 42 x and y coordinates.
fig <- fig %>% add_polygons(x = xym$x, y=xym$y)
However when I try to run this I get this error which I don't understand. Any idea what I'm doing wrong?
Error:
! Tibble columns must have compatible sizes.
• Size 42: Columns x and y.
• Size 11149: Columns text and color.
ℹ Only values of size one are recycled.
Run rlang::last_error() to see where the error occurred.

Two solutions below. First, adding inherit = FALSE to add_plygons().
library(tidyverse)
library(plotly)
xym<-data.frame(y=c(3,4,4,3),
x=c(5,5,6,6))
fig <- plot_ly(data = iris, x= ~Sepal.Length, y = ~Sepal.Width, color = ~Species, text = ~paste(Species), type = 'scatter', mode="markers")
fig <- fig %>% add_polygons(x = xym$x, y=xym$y, inherit = FALSE, showlegend = FALSE)
fig
Or, Switch the order of operations - make the polygons first, then the scatterplot.
Here is an example with iris data:
xym<-data.frame(x=c(5,5,6,6),
y=c(3,4,4,3))
# make an empty plot_ly object
fig <- plot_ly()
# add the polygons
fig<-fig %>% add_polygons(x = xym$x, y=xym$y)
# add the scatterplot
fig<-fig %>% add_trace(data = iris, x= ~Sepal.Length, y = ~Sepal.Width, color = ~Species, text = ~paste(Species), type ="scatter", mode="markers")
fig
referenced - Adding a polygon to a scatter plotly while retaining the hover info
and Adding a polygon to a scatter plotly

Related

R Plotly Heatmap Conditional Annotation with ifelse?

Follwoing:
R Heatmap: conditionally change label text colours with (ggplot2 or plotly)
I thought the code below would create a heatmap whose annotation is white if the value is greater than 5 (so in this case, when (X,Y)=(3,"C")) but it does not work. Any idea?
Thank you!
df<-tibble(Y=c("A","B","C"),
X=c(1,2,3),
Z=c(1,5,10))
df %>%
plot_ly(x = ~X, y=~Y, z=~Z, type='heatmap') %>%
add_annotations(text = ~Z,
showarrow = FALSE,
font = list(color = ~ifelse(Z>5,'white','black')))
Font colors weren't designed to be dynamic in Plotly. Even though add_annotations inherently understands that you want one 'add_annotation' for each value in Z, it does not assume that's what you mean for the font color. However, you can still have it changed on the fly with a UDF.
This function rebuilds the plot, then parses the annotations to assign colors.
that <- function(plt) {
plt <- plotly_build(plt) # build the plot to collect the data
lapply(1:length(plt$x$layout$annotations), # loop through annotations
function(j) {
this <- plt$x$layout$annotations[[j]] # collect annotation
colr <- ifelse(this$text > 5, "white", "black") # test for color
plt$x$layout$annotations[[j]]$font$color <<- colr # assign color
})
plt # return updated plot
}
The way that you use this is by just piping it to the end of your plot call. I didn't tie in exceptions for cases in which no color was specifically assigned. In other words, assign a color in your original plot call, it doesn't matter what color it is.
df %>%
plot_ly(x = ~X, y = ~Y, z = ~Z, type = 'heatmap') %>%
add_annotations(text = ~Z,
showarrow = FALSE,
font = list(color = "black")) %>% that() # <- I'm new!
I used the color sequence you chose, but I think this is the opposite of what you really wanted.
For example, if I swap the conditions for the colors in the function:
that <- function(plt) {
plt <- plotly_build(plt) # build the plot to collect the data
lapply(1:length(plt$x$layout$annotations), # loop through annotations
function(j) {
this <- plt$x$layout$annotations[[j]] # collect annotation
colr <- ifelse(this$text > 5, "black", "white") # test for color
plt$x$layout$annotations[[j]]$font$color <<- colr # assign color
})
plt # return updated plot
}
df %>%
plot_ly(x = ~X, y = ~Y, z = ~Z, type = 'heatmap') %>%
add_annotations(text = ~Z,
showarrow = FALSE,
font = list(color = "black")) %>% that()
Now you can see the text a lot better:
By the way, you could also call the plot as it is and use that(last_plot()) to rerender it with the new text colors.
Both plotly and ggplot2 have the function last_plot(); make sure you're calling the plotly version if you use this method.
Just an idea, you can also use a heatplot like this if you want to show a thresholded map:
ggplot(df, mapping = aes(x = X, y = Y, fill = Z>5, fill_max = 5)) + geom_tile()

How to log transform values for color in Plotly but to keep original values on colorbar?

I am trying to log transform values that are defining color on a Plotly graph, but I would like to keep original values on the Plotly color bar legend (not log-transformed numbers) in order to improve readability.
Here is the example of what I am trying to do on the mtcars data-set:
mtcars %>% plot_ly(x = ~hp,
y = ~qsec,
size = ~disp,
color = ~mpg)
and you will get this graph:
Let's say I want to log transform color variable (mpg) with this code:
mtcars %>% plot_ly(x = ~hp,
y = ~qsec,
size = ~disp,
color = ~log(mpg))
I will get this graph:
I am satisfied now with the graph, but now the colorbar on the right is having log() numbers.
My question is: how to log() transform color variable on a graph but keep the original numbers on the colorbar that are appropriately adjusted to new log colors?
So, on the one hand, I would like to have the original numbers on the second picture color bar, instead of 2.5, 3 and 3.5, but on the other hand, I would like to keep the color-positions of these numbers as they are on the log scale and without using ggplotly.
Similarly to this answer, this is a matter of using transformed values for the colour bar ticks, but untransformed values as labels.
Here is an option:
library(dplyr)
library(plotly)
# Define pretty breaks on transformed scale
brks_transformed <- pretty(log10(mtcars$mpg), n = 5)
# Breaks on the untransformed scale
brks_untransformed <- sprintf("%.1f", 10^brks_transformed)
mtcars %>%
plot_ly(
x = ~hp, y = ~qsec, size = ~ disp, fill = ~ "",
type = "scatter",
mode = "markers",
marker = list(
color = ~ log10(mpg),
line = list(width = 0),
colorbar = list(
tickmode = "array",
ticktext = brks_untransformed,
tickvals = brks_transformed)))

Remove continuous legend from plotly

I have a basic scatterplot that I've made in plotly (in R). I'm using a continuous input to color the data points which plotly converts into a gradient. However, the removelegend option doesn't remove a continuous legend the way it removes a discrete legend. Consider the example below.
data = mtcars
data$vs = as.character(data$vs)
plotly::plot_ly(
data = data,
x = ~disp,
y = ~mpg,
color = ~vs,
mode = "markers",
type = "scatter"
) %>%
layout(showlegend = FALSE)
plotly::plot_ly(
data = data,
x = ~disp,
y = ~mpg,
color = ~hp,
mode = "markers",
type = "scatter"
) %>%
layout(showlegend = FALSE)
Is there a way to remove the continuous legend?
The issue arises because in the continuous case plotly doesn't call it a legend, it's a color bar. The easiest way to remove it is to pipe in hide_colorbar()
plotly::plot_ly(
data = data,
x = ~disp,
y = ~mpg,
color = ~hp,
mode = "markers",
type = "scatter"
) %>%
hide_colorbar()

Add a line to a boxplot using plotly

Is it possible to add vertical line to a boxplot in plotly? I know it works in ggplot2, but I need it in plotly. Would be nice if I don't need to convert my static ggplot every time.
Here is a minimal example
plot_ly(x = ~rnorm(50), type = "box") %>%
add_trace(x = ~c(0.75),y=c(-2,0.5),type='scatter',mode='lines')
Instead of the line stoping before I want the line to go through the boxplot. In addition I want the same plot extent as the single boxplot.
Change the sequence of calls:
library(plotly)
plot_ly(x = ~c(0.75), y=c(-2,2), type='scatter', mode='lines') %>%
add_boxplot(x = ~rnorm(50), inherit = F) %>%
layout(yaxis = list(range = c(-2, 2)))

R plotly show xcoordinate on xaxis

I'm trying to create a graph with a similar x-axis format to this (from https://plot.ly/r/line-charts/):
code given:
library(plotly)
x <- c(1:100)
random_y <- rnorm(100, mean = 0)
data <- data.frame(x, random_y)
p <- plot_ly(data, x = ~x, y = ~random_y, type = 'scatter', mode = 'lines')
However, running the code on my machine produces this graph:
Notice that the x-coordinate hover is not there.
R version: 3.4.1
Plotly version: 4.7.1
Changing the hoverinfo and text tags in plot_ly just changes the hoverinfo over the graph. How do I show the same hovering x-coordinate in the first graph?
Update: setting hoverinfo = "text+x" and layout(hovermode = "x") shows the x-coordinate on the x-axis and the point tooltips.
Try setting hovermode to 'x'
p <- plot_ly(data, x = ~x, y = ~random_y, type = 'scatter', mode = 'lines') %>% layout(hovermode = 'x')
and it should work.

Resources