Horizontal line in R plotly, when xaxis is discrete - r

I would like to create a bar plot (with the plotly package), which (for some months) would have red horizontal line (gain to obtain). Plots below show my problem more precisely, I hope.
Code and data needed to obtain first plot:
library("plotly")
library("dplyr")
data.frame(miesiac_label = as.character(as.roman(c(1:12))),
miesiac = c(1:12),
ile = c(12000, 12100, 11100, 12000, 12000, 11900, 12200, 12100, 6000, 12100, 12100, 12100),
gain = c(rep(NA, 7), 11000, 12000, 12000, 12000, 12000)) -> dane
dane$miesiac_label <- factor(dane$miesiac_label, levels = dane[["miesiac_label"]])
plot_ly(dane) %>%
add_trace(x = ~miesiac_label, y = ~ile,
type = 'bar', marker = list(color = '#99d3df')) %>%
add_trace(x = ~miesiac_label, y = ~gain, name = 'Gain',
type = "scatter", mode='lines+markers', marker = list(color = 'red'),
line = list(color = 'red'))
I think that I should have a continuous scale to do this and after this just change x axis labels, but I don't know how to change those labels (I've tried to find it in google first, of course)...
Thanks a lot for your help!

Would something like that work for you. You could adjust the numbers in add_segments.
a <- list(
title = "miesiac_label",
showticklabels = TRUE,
tickmode= "array",
ticktext = as.character(as.roman(c(1:12))),
tickvals = c(1:12)
)
plot_ly(dane) %>%
add_bars(x = ~miesiac, y = ~ile) %>%
add_segments(x = 7.5, xend = 8.5, y = 10000, yend = ~10000, line = list(dash = "dash")) %>%
add_segments(x = 8.5, xend = 12.5, y = 12000, yend = ~12000, line = list(dash = "dash")) %>%
layout(showlegend = FALSE, xaxis = a)

I have managed to construct what you want using ggplot and the fantastic ggplotly()
Doing it normally for ggplot standards leads to hideous tooltips on hover, but that can be tweaked with the text aesthetic and the tooltip argument in the ggplotly call
for example:
ggplot(dane, aes(x = miesiac_label, y = ile)) +
geom_bar(aes(text = paste("x:", miesiac_label, "y:",ile)),
stat = "identity", fill = "#99d3df") +
geom_segment(aes(x = miesiac - 0.5, xend = miesiac + 0.5,
y = gain, yend = gain,
text = paste0("gain: ",gain))
, colour = "red"
, linetype = 2)
ggplotly(tooltip = "text")
Which results in the following plot:

Related

How to add vertical line between 2 markers in R plotly?

I just started using plotly in R, and I've made a plot like this
with a syntax like this:
maximum <- rnorm(30, mean = 20)
datasource <- rnorm(30, mean = 15)
minimum <- rnorm(30, mean = 10)
x <- c(1:30)
data <- data.frame(x,datasource,maximum,minimum)
fig <- plot_ly(data, x = ~x, y = ~datasource, name = 'trace 1', type = 'scatter', mode = 'lines+markers', marker = list(size = 10))
fig <- fig %>% add_trace(y = ~maximum, name = 'maximum', mode = 'markers', marker = list(size = 10))
fig <- fig %>% add_trace(y = ~minimum, name = 'minimum', mode = 'markers', marker = list(size = 10))
fig <- fig %>% layout(title = "XBAR CHART",
xaxis = list(title = "ID"),
yaxis = list (title = "Measurement Value (mm)"))
fig
I want to add a line connecting the minimum and maximum markers like the following.
I've been trying but haven't found the solution.
I hope I find a solution here.
thanks
calculate the points that defined the lines
v_lines <- mutate(rowwise(data),
vline=list(list(type="line",
x0=x,
x1=x,
y0=minimum,
y1=maximum,
line=list(color="blue")))) |> pull(vline)
add them to the layout
fig <- fig %>% layout(title = "XBAR CHART",
shapes= v_lines,
xaxis = list(title = "ID"),
yaxis = list (title = "Measurement Value (mm)"))
Like this?
ggplot(data=data, aes(x,datasource))+
geom_segment(data = data, aes(x = x, y = minimum, xend = x, yend = maximum), color = "light blue", size = 1)+
geom_line(data = data, aes(x = x, y = datasource), color= "blue", size = 1)+
geom_point(data=data, aes(x, minimum), color = "green", size=3)+
geom_point(data=data, aes(x, maximum), color = "orange", size=3)+
geom_point(color = "blue", size=3)+
xlab("X - axis text")+ylab("Y - axis text")+
theme_light(base_size = 18, base_rect_size = 1)

Setting colours in plotly R is not working (factors) in add markers

I'm trying to set the colour in R for "points" or markers in plotly with a custom palette. It doesn't work. I'm also trying to add a title to the graph, but it won't appear. In addition, I'd like to remove some elements of the legend (like the extra "z") and add a title to the legend elements. Nothing seems to work, even if it is present in the code.
library(plotly)
library(tidyverse)
set.seed(123456)
pal <- c("black", "orange", "darkgreen", "pink")
pal <- setNames(pal, levels(as.factor(c("gr1","gr2","gr3","gr4"))))
linedat = data.frame(x = rep(mean(1:50),2),
y = rep(mean(1:50),2),
z = c(0,1))
zoom = 3
pg = plotly::plot_ly(x = 1:50,
y = 1:50,
z = outer(1:50,1:50,"+")/100) %>%
add_surface(contours = list(
z = list(show = TRUE, start = 0, end = 1, size = 0.05)),
opacity = 1) %>%
add_markers(x = rnorm(50,25,5),
y = rnorm(50,25,5),
marker = list(opacity = 0.9),
type="scatter3d",
mode = "markers",inherit = FALSE,
colors = pal,
color = as.factor(sample(1:4,50,replace = T)),
z = rbinom(50,1,.5)) %>%
layout(scene=list(title = "Title won't show up????",
xaxis = list(title = 'trait1'),
yaxis = list(title = 'trait1',autorange = "reversed"),
camera = list(eye = list(x = cos(0.8*pi)*zoom, y = sin(pi*1.3)*zoom, z= 2.00)),
legend = list(title=list(text='<b> Groups </b>')))) %>%
add_trace(data=linedat, x=~x, y=~y, z=~z,
type="scatter3d", mode="lines",
line = list(color = pal[1],
width = 14),name = "Avg. data1")%>%
add_trace(data=linedat, x=~x+20, y=~y+20, z=~z,
type="scatter3d", mode="lines",
line = list(color = pal[4],
width = 14),name = "Avg. data2")
pg
See how here I'm able to set the colour of the points, but I'm not able to get the names of the colours to show in the legend (I modified the code to match what #Kat suggested):
library(plotly)
library(tidyverse)
set.seed(123456)
pal <- c("black", "orange", "darkgreen", "pink")
pal <- setNames(pal, levels(as.factor(c("gr1","gr2","gr3","gr4"))))
linedat = data.frame(x = rep(mean(1:50),2),
y = rep(mean(1:50),2),
z = c(0,1))
zoom = 3
pg = plotly::plot_ly(x = 1:50,
y = 1:50,
z = outer(1:50,1:50,"+")/100) %>%
add_surface(contours = list(
z = list(show = TRUE, start = 0, end = 1, size = 0.05)),
opacity = 1, colorbar = list(title = "Only one Z")) %>%
add_markers(x = rnorm(50,25,5),
y = rnorm(50,25,5),
marker = list(color = pal[as.factor(sample(1:4,50,replace = T))],opacity = 0.9),
type="scatter3d",
mode = "markers",inherit = FALSE,
colors = pal,
z = rbinom(50,1,.5)) %>%
layout(title = "Title that won't show",
margin = list(t = 40),
legend = list(title = list(
text = "<br>Legends deserve names, too")),
scene=list(xaxis = list(title = 'trait1'),
yaxis = list(title = 'trait1',autorange = "reversed"),
camera = list(eye = list(x = cos(0.8*pi)*zoom,
y = sin(pi*1.3)*zoom, z= 2.00)))) %>%
add_trace(data=linedat, x=~x, y=~y, z=~z,
type="scatter3d", mode="lines",
line = list(color = pal[1],
width = 14),name = "Avg. data1")%>%
add_trace(data=linedat, x=~x+20, y=~y+20, z=~z,
type="scatter3d", mode="lines",
line = list(color = pal[4],
width = 14),name = "Avg. data2");pg
Your original plot_ly call and add_trace calls can remain as is. I've included the changes needed for the layout call and added the call needed for colorbar.
The layout first.
layout(title = "Title that won't show", # <------ give my plot a name
margin = list(t = 40), # don't smash that title, either
legend = list(title = list(
text = "<br>Legends deserve names, too")), # <--- name my legend
scene=list(title = "Title won't show up????", # <- this can go away
xaxis = list(title = 'trait1'),
yaxis = list(title = 'trait1',autorange = "reversed"),
camera = list(eye = list(x = cos(0.8*pi)*zoom,
y = sin(pi*1.3)*zoom, z= 2.00)),
legend = list(title=list(text='<b> Groups </b>')))) %>%
colorbar(title = "Only one Z") # <--- give me one z colorbar title
(Some colors are different in the image; I didn't realize I had the pal object...sigh)
Update
This addresses your additional questions.
First, I'm not getting an error from the method in which I title the color bar. You'll have to share what error you're getting.
I didn't realize that it was ignoring the colors you set in markers, either. The easiest way to address this is to call that trace first. Since nothing else was declared within markers, I called opacity outside of the list, but it's fine the way you have it.
First, I commented out the setNames call, because that won't work for the marker's trace and it doesn't matter to the other traces.
library(plotly)
set.seed(123456)
pal <- c("black", "orange", "darkgreen", "pink")
# pal <- setNames(pal, levels(as.factor(c("gr1","gr2","gr3","gr4"))))
linedat = data.frame(x = rep(mean(1:50),2),
y = rep(mean(1:50),2),
z = c(0,1))
zoom = 3
I made plot_ly() empty and put all the data for the surface in that trace. I also added inherit = false so that the layout could go at the end without the data errors.
set.seed(123456)
pg = plotly::plot_ly() %>%
add_trace(inherit = F,
x = rnorm(50,25,5),
y = rnorm(50,25,5),
type="scatter3d",
mode = "markers",
opacity = .8,
colors = pal,
color = as.factor(sample(1:4, 50, replace = T)),
z = rbinom(50,1,.5)) %>%
add_surface(x = 1:50,
y = 1:50,
z = outer(1:50,1:50,"+")/100,
colorscale = "Viridis",
contours = list(
z = list(show = TRUE, start = 0, end = 1, size = 0.05)),
opacity = 1) %>%
add_trace(data=linedat, x=~x, y=~y, z=~z,
type="scatter3d", mode="lines",
line = list(color = pal[1],
width = 14),name = "Avg. data1", inherit = F) %>%
add_trace(data=linedat, x=~x+20, y=~y+20, z=~z,
type="scatter3d", mode="lines",
line = list(color = pal[4],
width = 14),name = "Avg. data2", inherit = F) %>%
The last part is the layout, but this is not different than my original answer.
layout(title = "Title that won't show", # <------ give my plot a name!
margin = list(t = 40), # don't smash that title, either
legend = list(title = list(
text = "<br>Legends deserve names, too"),
tracegroupgap = 350), # <--- name my legend!
scene=list(title = "Title won't show up????", # <--- this can go away!
xaxis = list(title = 'trait1'),
yaxis = list(title = 'trait1',autorange = "reversed"),
camera = list(eye = list(x = cos(0.8*pi)*zoom,
y = sin(pi*1.3)*zoom, z= 2.00)),
legend = list(title=list(text='<b> Groups </b>')))) %>%
colorbar(title = "Only one Z") # <--- give me one z for the title!
pg

Image and plotly plot side by side in R markdown

I am trying to show an image and a plot (plotly gauge) side-by-side in R markdown, however only a blank graph shows for the image. I have imported the image into plotly and am attempting to use subplot to show them side by side. Any advice on what I'm missing?
# Photo
photo <- plot_ly(domain = list(x = c(0, 0.5), y = c(0, 1)))%>%
layout(
images = list(source = "C:/Users/Name/Documents//Image.PNG"
))
# Gauge value
x <- mean(df$variable)
# Plot
fig1 <- plot_ly(
value = x,
number = list(suffix = "%"),
title = list(text = "Title"),
type = "indicator",
mode = "gauge+number",
gauge = list(
axis =list(range = list(NULL, 100)),
steps = list(
list(range = c(0, 78), color = "white"),
list(range = c(78, 88), color = "green"),
list(range = c(88, 100), color = "white")),
bar = list(color = "black")),
domain = list(x = c(0.5, 1), y = c(0, 1)))
subplot(photo, add_trace(fig1))
I didn't try in RMarkdown but I would try this:
library(plotly)
library(EBImage) # BiocManager::install("EBImage")
p1 <- plot_ly(economics, x = ~pop)
img <- readImage("mobiussolid.png")
p2 <- plot_ly(type = "image", z = img*255) %>%
layout(margin=list(l=10, r=10, b=0, t=0),
xaxis=list(showticklabels=FALSE, ticks=""),
yaxis=list(showticklabels=FALSE, ticks=""))
subplot(p1, p2)

R plotly(): Adding regression line to a correlation scatter plot

I would like to add the regression line to my correlation scatter plot. Unfortunately this doesn't really work with plot_ly(). I've already tried some solutions from other posts in this forum, but it doesn't work.
My data frame looks like the following (only a smart part of it):
My code for the plot and the actual plot-output look like the following:
CorrelationPlot <- plot_ly(data = df.dataCorrelation, x = ~df.dataCorrelation$prod1,
y = ~df.dataCorrelation$prod2, type = 'scatter', mode = 'markers',
marker = list(size = 7, color = "#FF9999", line = list(color = "#CC0000", width = 2))) %>%
layout(title = "<b> Correlation Scatter Plot", xaxis = list(title = product1),
yaxis = list(title = product2), showlegend = FALSE)
What I want to have is something like this:
which I have produced with the ggscatter() function:
library(ggpubr)
ggscatter(df.dataCorrelation, x = "prod1", y = "prod2", color = "#CC0000", shape = 21, size = 2,
add = "reg.line", add.params = list(color = "#CC0000", size = 2), conf.int = TRUE,
cor.coef = TRUE, cor.method = "pearson", xlab = product1, ylab = product2)
HOW do I get the regression line with plot_ly()??
CODE EDITING:
CorrelationPlot <- plot_ly(data = df.dataCorrelation, x = ~df.dataCorrelation$prod1,
y = ~df.dataCorrelation$prod2, type = 'scatter', mode = 'markers',
marker = list(size = 7, color = "#FF9999",
line = list(color = "#CC0000", width = 2))) %>%
add_trace(x = ~df.dataCorrelation$fitted_values, mode = "lines", type = 'scatter',
line = list(color = "black")) %>%
layout(title = "<b> Correlation Scatter Plot", xaxis = list(title = product1),
yaxis = list(title = product2), showlegend = FALSE)
GIVES:
How do I get here a line for the regression line??
I don't think there's a ready function like ggscatter, most likely you have to do it manually, like first fitting the linear model and adding the values to the data.frame.
I made a data.frame that's like your data:
set.seed(111)
df.dataCorrelation = data.frame(prod1=runif(50,20,60))
df.dataCorrelation$prod2 = df.dataCorrelation$prod1 + rnorm(50,10,5)
fit = lm(prod2 ~ prod1,data=df.dataCorrelation)
fitdata = data.frame(prod1=20:60)
prediction = predict(fit,fitdata,se.fit=TRUE)
fitdata$fitted = prediction$fit
The upper and lower bounds of the line are simply 1.96* standard error of prediction:
fitdata$ymin = fitdata$fitted - 1.96*prediction$se.fit
fitdata$ymax = fitdata$fitted + 1.96*prediction$se.fit
We calculate correlation:
COR = cor.test(df.dataCorrelation$prod1,df.dataCorrelation$prod2)[c("estimate","p.value")]
COR_text = paste(c("R=","p="),signif(as.numeric(COR,3),3),collapse=" ")
And put it into plotly:
library(plotly)
df.dataCorrelation %>%
plot_ly(x = ~prod1) %>%
add_markers(x=~prod1, y = ~prod2) %>%
add_trace(data=fitdata,x= ~prod1, y = ~fitted,
mode = "lines",type="scatter",line=list(color="#8d93ab")) %>%
add_ribbons(data=fitdata, ymin = ~ ymin, ymax = ~ ymax,
line=list(color="#F1F3F8E6"),fillcolor ="#F1F3F880" ) %>%
layout(
showlegend = F,
annotations = list(x = 50, y = 50,
text = COR_text,showarrow =FALSE)
)
Another option is using ggplotly as
library(plotly)
ggplotly(
ggplot(iris, aes(x = Sepal.Length, y = Petal.Length))+
geom_point(color = "#CC0000", shape = 21, size = 2) +
geom_smooth(method = 'lm') +
annotate("text", label=paste0("R = ", round(with(iris, cor.test(Sepal.Length, Petal.Length))$estimate, 2),
", p = ", with(iris, cor.test(Sepal.Length, Petal.Length))$p.value),
x = min(iris$Sepal.Length) + 1, y = max(iris$Petal.Length) + 1, color="steelblue", size=5)+
theme_classic()
)

Source Annotation in Plotly

Is there a way to insert a source annotation below the x-axis label in Plotly? I can get an annotation below the x-axis, but if I change the margins, the annotation gets cut off. For now, I am able to put an annotation between the x-axis and the x-axis label. Below is a MWE for the included chart.
df <- data.frame(x = 1:10, y = 1:10)
plot_ly(data = df, x = ~x, y = ~y, type = 'scatter', mode = 'lines') %>%
layout(title = 'Sample Chart',
margin = list(l = 50, r = 50, t = 60, b = 60),
annotations = list(text = 'Source: U.S. Census Bureau.',
font = list(size = 12),
showarrow = FALSE,
xref = 'paper', x = -0.03,
yref = 'paper', y = -0.2))
I would like to move the "Source: U.S. Census Bureau" below the x-axis title.
You need to add line breaks using html tags
plot_ly(data = df, x = ~x, y = ~y, type = 'scatter', mode = 'lines') %>%
+ layout(title = 'Sample Chart',xaxis=list(
+ title = 'x <br> Source: U.S. Census Bureau.'),
+ margin = list(l = 50, r = 50, t = 60, b = 60))

Resources