plotly fill color transparency in R shiny - r

In R and plotly. How can I tried to use alpha to control the transparency of a grouped scatter plot.
I followed the example in Plotly's fillcolor defaults to half-transparency, want no-transparency:
df <- data.frame(x = rep(LETTERS[1:5], 3),
y = rexp(15, rate = 0.5),
z = c(rep("Adam", 5), rep("Arthur", 5), rep("Ford", 5)))
df <- arrange(df, desc(z))
plot_ly(df, x = ~x, y = ~y, color = ~z, type = 'scatter', stackgroup = 'one',
groupnorm = 'percent', colors = gg_color(Nv), alpha = 1, alpha_stroke = 1)
But the fill colours are transparent and alpha does not seem to do anything.
The solution given in Plotly's fillcolor defaults to half-transparency, want no-transparency works:
library(htmlwidgets)
library(htmltools)
fillOpacity = function(., alpha = 0.5) {
css = sprintf("<style> .js-fill { fill-opacity: %s !important; } </style>", alpha)
prependContent(., HTML(css))
}
plot_ly(df, x = ~x, y = ~y, color = ~z, type = 'scatter', stackgroup = 'one',
groupnorm = 'percent', colors = gg_color(Nv), alpha = 1, alpha_stroke = 1) %>%
fillOpacity(alpha = 1)
Works:
However, in Shiny this gives the following warning and the opacity is lost
Warning in renderWidget(instance) :
Ignoring prepended content; prependContent can't be used in a Shiny render call
Is there a way to fix this?
Note: The second figure is a snip in windows, because when clicking on the download png plotly button, the second graph still downloads the graph as transparent. The two issues are probably related.

I looked here https://plotly.com/python/filled-area-plots/ and used fill='tonexty'. Now the alpha = 1 works and controls the transparency of the fill.
ply = plot_ly(df, x = ~x, y = ~y, color = ~z, type = 'scatter', stackgroup = 'one',
groupnorm = 'percent', alpha = 1, alpha_stroke = 1, mode = 'marker', opacity=1, fill='tonexty');ply
gives:
I still think this is an oversight in the API. when stackgroup = 'one', groupnorm = 'percent' the fill is automatically fill='tonexty'. there shouldn't be a need to add it in order to manipulate the opacity. Also, alpha = 1 becoming active only because works fill='tonexty' has been added is confusing.

Related

drawing rectangle on plotly R

I would like to draw a rectangle polygon over a plotly plot that uses dates. As a toy example my code is
library(tidyverse)
library(plotly)
df <- tibble(daydate = dmy(c("01-01-2022", "01-02-2022", "15-02-2022", "27-02-2022")),
value = runif(4, 0, 100))
plot_ly(df, x = ~daydate, y = ~value, color = I("#9B4393"), type = 'scatter', mode = 'lines')
I would like to draw a rectangle that spans the dates "01-02-2022" to "15-02-2022", and from 0 to 100. Also, I would like to have the rectangular area grey colour that is quite transparent.
Many thanks
Define a rectangle:
my_rectangle <- list(
type = "rect",
fillcolor = "grey",
line = list(color = "black"),
opacity = 0.3,
x0 = "2022-02-01",
x1 = "2022-02-15",
xref = "x",
y0 = 0,
y1 = 100,
yref = "y"
)
Add it to the plot:
plot_ly(
df,
x = ~daydate,
y = ~value,
color = I("#9B4393"),
type = "scatter",
mode = "lines"
) |>
layout(
shapes = list(
my_rectangle
)
)
The R plotly documentation sets out how you can draw and style rectangles and various other shapes.

R Plotly how to link text to bubbles in order to remove it when click on legend

With plotly on R, I have a bubble scatter plot and I want to add black text on each bubble. I also have my bubbles colored following a column of my data frame (Type: Yes or No). On my legend, when I click on "Yes" it will remove the bubbles linked to "Yes" but the text is staying, even if I added a 'legendgroup=~Type' in both traces.
How can I remove the text linked to the bubble when the user click on the legend ?
It is possible but only if I set 'color = ~Type' in my text trace, but I want to keep the text in black.
Example :
df <- data.frame(Projet=c("A", "B", "C"), x=c(0.2, 0.4, 0.6), y=c(0.6, 0.5, 0.1), Size=c(2,5,8), Type=c("Yes", "Yes", "No"))
fig <- plot_ly(df, x = ~ x, y = ~y) %>%
add_trace(color = ~Type, size = ~Size,
type = 'scatter', mode = 'markers',
sizes = c(20, 80),
marker = list(symbol = 'circle', sizemode = 'diameter',line = list(width = 2, color = 'gray60')),
hovertext = ~paste('Projet:', Projet, '<br>Size (kE):', Size),
hoverinfo="text", legendgroup=~Type) %>%
add_trace(type="scatter", mode="text", text=~Projet, showlegend=F, legendgroup=~Type)
fig
Which gives :
And if I click on "Yes" in the legend :
=> I want to remove the "A" and "B" text in this case
Thanks !
When I looked at your Plotly object, you assigned three group names to the parameter legendgroup. The reason it worked in your initial call add_trace is that Plotly will split a trace by color. In your call for text, everything is the same color, so it didn't automatically split the trace.
In your call for the text, you need to add split to split the trace.
Check it out
library(plotly)
df <- data.frame(Project = c("A", "B", "C"), x = c(0.2, 0.4, 0.6),
y = c(0.6, 0.5, 0.1), Size = c(2,5,8),
Type = c("Yes", "Yes", "No"))
fig <- plot_ly(df, x = ~ x, y = ~y) %>%
add_trace(color = ~Type, size = ~Size,
type = 'scatter', mode = 'markers',
sizes = c(20, 80),
marker = list(symbol = 'circle', sizemode = 'diameter',
line = list(width = 2, color = 'gray60')),
hovertext = ~paste('Project:', Project, '<br>Size (kE):', Size),
hoverinfo = "text", legendgroup = ~Type) %>%
add_trace(type = "scatter", mode = "text", text = ~Project,
showlegend = F, legendgroup = ~Type, split = ~Type) # <- I'm new!
fig

Set the y limits of an added average line of a plotly plot

I have created a basic plotly filled plot and I am trying to add an average line with:
library(plotly)
week<-c(2,1,3)
pts<-c(10,20,30)
wex<-data.frame(week,pts)
wex <- wex[order(wex$week), ]
plot_ly(x = ~wex$week, y = ~wex$pts, type = 'scatter', mode = 'lines',
fill = 'tozeroy')%>%
add_segments(x = 0, xend = max(wex$week), y = mean(wex$pts), yend =mean(wex$pts) )
but instead of a single line I get a whole area filled. I guess it has to do with yend argument but it does not make sense as it is the same as the y argument.
It seems the fill='tozeroy' is kept for the add_segments() call.
This works:
library(plotly)
week<-c(2,1,3)
pts<-c(10,20,30)
wex<-data.frame(week,pts)
wex <- wex[order(wex$week), ]
wex
plot_ly(x = ~wex$week, y = ~wex$pts, type = 'scatter', mode = 'lines',
fill = 'tozeroy')%>%
add_segments(x = 0, xend = max(wex$week), y = mean(wex$pts), yend =mean(wex$pts),fill = 'none' )
I added fill = 'none' in add_segments()

Viewing hover info for overlapping scatter points in Plotly R

I was surpised I was not able to google this solution, so I thought i'd put up a post. Surely others have the same issue...
The issue I have is that when two or more scatter points overlap (i.e. same x and y), the hover information only shows the info of the top point.
Example:
df <- data.frame(ID=1:6, x=c(5:9, 7), y=c(1:5, 3)+10, info=paste('Hover information: ',c(LETTERS[c(1:6)])))
df
plot_ly(df) %>%
add_trace(x = ~x,
y = ~y,
type = 'scatter',
mode = 'markers',
marker = list(color = 1:6,
symbol = 1:6,
size = 25),
hoverinfo = "text",
text = df$info)
It is possible to make BOTH hoverinfo for the middle point to show up? Possibly as:
Hover information: C
Hover information: F
You can try to use add_markers() and jitter, e.g:
plot_ly(df) %>%
add_markers(x = ~jitter(x, 1),
y = ~jitter(y, 1),
type = 'scatter',
mode = 'markers',
marker = list(color = 1:6,
symbol = 1:6,
size = 25),
hoverinfo = "text",
text = ~info)
But to get multiple information as you designed, maybe you need to modify your dataframe (but you will lose the colour code):
df$info <- as.character(df$info)
df$combined_info[1] <- df$info[1]
for(i in 2:nrow(df)){
df$combined_info[i] <- df$info[i]
for(j in 2:i-1){
if((df$x[j] == df$x[i]) && (df$y[j] == df$y[i])){
df$combined_info[i] <- paste0(df$combined_info[j], "<br>",
df$info[i])
}
}
}
And then you can use the original plotly code, while changing the "text" argument:
plot_ly(df) %>%
add_trace(x = ~x,
...
text = ~combined_info)

Boxplot next to a scatterplot in R with plotly

I created a scatter plot with plotly in R. Now I want to plot a boxplot with different data next to the scatter plot. I want to use plotly for this.
The result should look like this. Can someone help me please, I have no idea how to do that.
My code so far is
plot_ly(ds, x = ~x, y = ~y , mode = "markers", name = "Clusters", opacity = point.opacity,
text = ds$id,
hoverinfo = "text",
marker = list(symbol = point.symbol, color = ~color, size = point.size,
line = list(color = "#262626", width = point.linewidth, opacity = point.lineopacity)),
showlegend = F)
Here is an example on how to make a scatter with marginal box plots with plotly:
library(plotly)
data(iris)
create, three plots for the data: one for the scatter, two for the appropriate box plots, and one additional empty plot. Use the subplot function to arrange them:
subplot(
plot_ly(data = iris, x = ~Petal.Length, type = 'box'),
plotly_empty(),
plot_ly(data = iris, x = ~Petal.Length, y = ~Petal.Width, type = 'scatter',
mode = 'markers'),
plot_ly(data = iris, y = ~Petal.Width, type = 'box'),
nrows = 2, heights = c(.2, .8), widths = c(.8,.2), margin = 0,
shareX = TRUE, shareY = TRUE) %>%
layout(showlegend = F)

Resources