I'm just starting to use plotly and I haven't been able to do something as simple as adding objects to an existing plot. How can I add line segments to an existing empty plot?
I've tried this, but every call of add_segment creates a new plot with only one segment:
p<-plot_ly()
add_segment(p,x=0,y=1,x=5,y=1)
add_segment(p,x=0,y=4,x=5,y=4)
What am I doing wrong?
The answer: use the %>% operator like this:
p <- plot_ly(data, x = ~x)
p <- p %>% add_trace(y = ~trace_0, name = 'trace 0',mode = 'lines')
p
The details:
One approach is to use the piping %>% operator from this example where the following plot is produced by the code below:
Plot:
Code:
library(plotly)
set.seed(1)
trace_0 <- rnorm(100, mean = 5)
trace_1 <- rnorm(100, mean = 0)
trace_2 <- rnorm(100, mean = -5)
x <- c(1:100)
data <- data.frame(x, trace_0, trace_1, trace_2)
p <- plot_ly(data, x = ~x) %>%
add_trace(y = ~trace_0, name = 'trace 0',mode = 'lines') %>%
add_trace(y = ~trace_1, name = 'trace 1', mode = 'lines+markers') %>%
add_trace(y = ~trace_2, name = 'trace 2', mode = 'markers')
p
Step by step using %>%:
Code Step 1:
# step 1
p <- plot_ly(data, x = ~x)
# plot
p
Plot step 1:
Code step 2:
# step 1
p <- plot_ly(data, x = ~x)
# step 2
p <- p %>% add_trace(y = ~trace_0, name = 'trace 0',mode = 'lines')
# plot
p
Plot step 2:
Code all steps:
# step 1
p <- plot_ly(data, x = ~x)
# step 2
p <- p %>% add_trace(y = ~trace_0, name = 'trace 0',mode = 'lines')
# step 3
p <- p %>% add_trace(y = ~trace_1, name = 'trace 1', mode = 'lines+markers')
# step 4
p <- p %>% add_trace(y = ~trace_2, name = 'trace 2', mode = 'markers')
# plot
p
Plot all steps:
Edit: Response to comments
Is there any way to add elements without using the pipe?
Not to my knowledge, but I'm hoping someone proves me wrong. Since this is an [R] question, I'm guessing you're more familiar with building ggplot plots stepwise like this:
library(ggplot2)
g <- ggplot(diamonds, aes(x=carat, y=price, color=cut)) + geom_point()
g <- g + geom_smooth()
g
The + approach will not work for plotly though:
Code:
# step 1
p <- plot_ly(data, x = ~x)
# step 2
p <- p + add_trace(y = ~trace_0, name = 'trace 0',mode = 'lines')
Error:
Error in add_data(p, data) : argument "p" is missing, with no default
And there's absolutely no reason to fear the %>% operator. a %>% b simply means something along the lines of Take a, and do b with it. To my knowledge, this was first seen in the magrittr package, and is widely used in the fantastic dplyr package. I'm mostly messing around with python at the time, but this really makes me miss R
Related
I need to plot a line chart that has more than 50 different lines. I am using RColorBrewer to generate 50 unique colors to plot it. However some of the generated colors are very hard to read (e.g. bright yellow). Is there anyway to generate a set of colors that are easier to read?
library(tidyverse)
library(RColorBrewer)
library(plotly)
colors_ = colorRampPalette(brewer.pal(10,"Spectral"))(50)
grps = sort(rep(c(1:50),2)) %>% as.character() %>% unique
dat = data.frame(x = rep(c(1,2),50) , y = sort(rep(c(1:50),2)) , grp =as.character(sort(rep(c(1:50),2))) )
p = plot_ly(dat ,type = 'scatter', mode = 'lines')
for (i in 1:50){
p <- p %>% add_trace(data = filter(dat , grp ==grps[i] ) , x = ~x, y=~y,
line = list(color = colors_[i]),
text = grps[i]
)
}
p
How do I add multiple regression lines to the same plot in plotly?
I want to graph the scatter plot, as well as a regression line for each CATEGORY
The scatter plot plots fine, however the graph lines are not graphed correctly (as compared to excel outputs, see below)
df <- as.data.frame(1:19)
df$CATEGORY <- c("C","C","A","A","A","B","B","A","B","B","A","C","B","B","A","B","C","B","B")
df$x <- c(126,40,12,42,17,150,54,35,21,71,52,115,52,40,22,73,98,35,196)
df$y <- c(92,62,4,23,60,60,49,41,50,76,52,24,9,78,71,25,21,22,25)
df[,1] <- NULL
fv <- df %>%
filter(!is.na(x)) %>%
lm(x ~ y + y*CATEGORY,.) %>%
fitted.values()
p <- plot_ly(data = df,
x = ~x,
y = ~y,
color = ~CATEGORY,
type = "scatter",
mode = "markers"
) %>%
add_trace(x = ~y, y = ~fv, mode = "lines")
p
Apologies for not adding in all the information beforehand, and thanks for adding the suggestion of "y*CATEGORY" to fix the parallel line issue.
Excel Output
https://i.imgur.com/2QMacSC.png
R Output
https://i.imgur.com/LNypvDn.png
Try this:
library(plotly)
df <- as.data.frame(1:19)
df$CATEGORY <- c("C","C","A","A","A","B","B","A","B","B","A","C","B","B","A","B","C","B","B")
df$x <- c(126,40,12,42,17,150,54,35,21,71,52,115,52,40,22,73,98,35,196)
df$y <- c(92,62,4,23,60,60,49,41,50,76,52,24,9,78,71,25,21,22,25)
df[,1] <- NULL
df$fv <- df %>%
filter(!is.na(x)) %>%
lm(y ~ x*CATEGORY,.) %>%
fitted.values()
p <- plot_ly(data = df,
x = ~x,
y = ~y,
color = ~CATEGORY,
type = "scatter",
mode = "markers"
) %>%
add_trace(x = ~x, y = ~fv, mode = "lines")
p
In creating a trend line for a scatter plot, I am using add_trace to add a linear trend line.
When the data only has one "series" of data, i.e. there is only one group of coordinates, the code below works fine. However, when I introduce a number of series, the "trend line" looks like this:
Here is the relevant part of the code:
p <- plot_ly(filteredFull(), x=Relative.Time.Progress, y=cumul.ans.keystroke,
mode='markers', color=KeystrokeRate, size=KeystrokeRate,
marker=list(sizeref=100), type='scatter',
hoverinfo='text', text=paste("token: ",Token, "Keystrokes: ",
KeystrokeCount)) %>%
layout(
xaxis=list(range=c(0,1)),
yaxis=list(range=c(0,max(filteredFull()$cumul.ans.keystroke)))
)
lm.all <- lm(cumul.ans.keystroke ~ Relative.Time.Progress,
data=df)
observe(print(summary(lm.all)))
p <- add_trace(p, y=fitted(lm.all), x=Relative.Time.Progress,
mode='lines') %>%
layout(
xaxis= list(range = c(0,1))
)
p
I can add more code, or try to make a minimal working example, if necessary. However, I'm hoping that this is a famililar problem that is obvious from the code.
I think you'll need to specify the data = ... argument in add_trace(p, y=fitted(lm.all), x=Relative.Time.Progress, mode='lines').
The first trace seems to be a subset but the second trace uses the regression fitted values which are obtained by fitting a regression model to the entire dataset.
There might be a mismatch between Relative.Time.Progress in filteredFull() vs df.
Here's an example. Hopefully helps...
library(plotly)
df <- diamonds[sample(1:nrow(diamonds), size = 500),]
fit <- lm(price ~ carat, data = df)
df1 <- df %>% filter(cut == "Ideal")
plot_ly(df1, x = carat, y = price, mode = "markers") %>%
add_trace(x = carat, y = fitted(fit), mode = "lines")
plot_ly(df1, x = carat, y = price, mode = "markers") %>%
add_trace(data = df, x = carat, y = fitted(fit), mode = "lines")
It changed now a bit, the following code should work fine:
df <- diamonds[sample(1:nrow(diamonds), size = 500),]
fit <- lm(price ~ carat, data = df)
df1 <- df %>% filter(cut == "Ideal")
plot_ly() %>%
add_trace(data = df1, x = ~carat, y = ~price, mode = "markers") %>%
add_trace(data = df, x = ~carat, y = fitted(fit), mode = "lines")
Need to start with empty plotly and add traces.
The two separate charts created from data.frame work correctly when created using the R plotly package.
However,
I am not sure how to combine them into one (presumably with the add_trace function)
df <- data.frame(season=c("2000","2000","2001","2001"), game=c(1,2,1,2),value=c(1:4))
plot_ly(df, x = game, y = value, mode = "markers", color = season)
plot_ly(subset(df,season=="2001"), x = game, y = value, mode = "line")
Thanks in advance
The answer given by #LukeSingham does not work anymore with plotly 4.5.2.
You have to start with an "empty" plot_ly() and then to add the traces:
df1 <- data.frame(season=c("2000","2000","2001","2001"), game=c(1,2,1,2), value=c(1:4))
df2 <- subset(df, season=="2001")
plot_ly() %>%
add_trace(data=df1, x = ~game, y = ~value, type="scatter", mode="markers") %>%
add_trace(data=df2, x = ~game, y = ~value, type="scatter", mode = "lines")
here is a way to do what you want, but with ggplot2 :-) You can change the background, line, points color as you want.
library(ggplot2)
library(plotly)
df_s <- df[c(3:4), ]
p <- ggplot(data=df, aes(x = game, y = value, color = season)) +
geom_point(size = 4) +
geom_line(data=df_s, aes(x = game, y = value, color = season))
(gg <- ggplotly(p))
There are two main ways you can do this with plotly, make a ggplot and convert to a plotly object as #MLavoie suggests OR as you suspected by using add_trace on an existing plotly object (see below).
library(plotly)
#data
df <- data.frame(season=c("2000","2000","2001","2001"), game=c(1,2,1,2),value=c(1:4))
#Initial scatter plot
p <- plot_ly(df, x = game, y = value, mode = "markers", color = season)
#subset of data
df1 <- subset(df,season=="2001")
#add line
p %>% add_trace(x = df1$game, y = df1$value, mode = "line")
I am trying to add layers in plotly programmatically but can't seem to get around it's lazy evaluation. Example:
p <- plot_ly()
for(kk in 1:5) {
tmp <- cbind(rnorm(1) + 0.05*rnorm(15),rnorm(1) + 0.05*rnorm(15))
p %<>% add_trace(x = tmp[,1], y = tmp[,2], type = "scatter", mode = "markers")
}
In this example I was trying to plot a gaussian mixture model, however, the arguments to plotly aren't evaluated until they are viewed, so all five layers contain only the final value of tmp. The command plotly_build is supposed force evaluation but I can't find examples of its usage and apparently I'm doing it wrong.
p <- plot_ly()
for(kk in 1:5) {
tmp <- cbind(rnorm(1) + 0.05*rnorm(15),rnorm(1) + 0.05*rnorm(15))
p %<>% add_trace(x = tmp[,1], y = tmp[,2], type = "scatter", mode = "markers")
plotly_build(p)
}
Still gives the same result. What am I doing wrong?
p <- plot_ly()
for(kk in 1:5) {
tmp <- cbind(rnorm(1) + 0.05*rnorm(15),rnorm(1) + 0.05*rnorm(15))
p %<>% add_trace(x = tmp[,1], y = tmp[,2], type = "scatter", mode = "markers", evaluate = TRUE)
}
There is an evaluate argument to plotly.