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.
Related
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
I'm making some visualization using R Studio. I have a list of dataframes:
tickers_df <- read.csv('tickers.csv')
v_df <- split(tickers_df, tickers_df$pair_code)
Now I want to make a plot for each dataframe within v_df in its own Viewer window. I'm doing:
for (pair_df in v_df) {
col_name <- names(pair_df)[4:9]
colors <- c('green', 'darkgreen', 'red', 'darkred', 'blue', 'darkblue')
df_layout <- data.frame(col_name, colors)
p <- plot_ly()
for (i in 1:nrow(df_layout)) {
col_name <- as.character(df_layout[i, 1])
p <-
add_trace(
p,
x = pair_df$step,
y = pair_df[, col_name],
name = col_name,
type = 'scatter',
mode = "lines",
line = list(color = df_layout[i, 2], width = 1)
)
p <- layout(p, title = pair_df$pair_code[[1]])
}
p
}
But this code doesn't work as expected - it shows no charts at all.
How can I draw many plotly charts within a loop?
And btw what is the meaning of last line with only p variable? Like in this example:
p <- plot_ly( x = df$time.1, y = df$total_profit, line = list(color = 'darkred'))
p #what is this standing for?
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
I found an example to add lines to a plot_ly plot by using the add_trace command. How can I add a list of lines to plot without using add_trace multiple times?
I tried a for loop to add the traces but this doesn't work as expected.
my_lines <- list(
list(x=1:10, y=2:11, color='red'),
list(x=1:10, y=0:9, color='blue'),
list(x=1:10, y=3:12, color='green')
)
p <- plot_ly()
p
for(line in my_lines) { p <- add_trace(p, y=line[['y']], x=line[['x']],
marker=list(color=line[['color']]))
}
p
But this for example works as expected.
p <- plot_ly()
p <- add_trace(p, y=my_lines[[1]][['y']], x=my_lines[[1]][['x']],
marker=list(color=my_lines[[1]][['color']]))
p <- add_trace(p, y=my_lines[[2]][['y']], x=my_lines[[2]][['x']],
marker=list(color=my_lines[[2]][['color']]))
p <- add_trace(p, y=my_lines[[3]][['y']], x=my_lines[[3]][['x']],
marker=list(color=my_lines[[3]][['color']]))
p
I believe with the release of plotly 4.0 calling any of the add_* family of functions forces evaluation so there is no need to call evaluate = T anymore
So, something like this should work fine:
devtools::install_github("ropensci/plotly")
library(plotly)
p <- plot_ly()
for(i in 1:5){
p <- add_trace(p, x = 1:10, y = rnorm(10), mode = "lines")
}
p
You need to set evaluate = TRUE to force evalutation / avoid lazy evaluation
p <- plot_ly()
p
for(line in my_lines) { p <- add_trace(p, y=line[['y']], x=line[['x']],
marker=list(color=line[['color']]),
evaluate = TRUE)
}
p
You can transform your inputs into a long-form data frame first, then plot using the split argument.
library(plotly)
library(reshape2)
my_lines = data.frame(x = 1:10, red = 2:11, blue = 0:9, green = 3:12)
my_lines_long = reshape2::melt(my_lines, id.vars = "x")
fig = plotly::plot_ly(my_lines_long, x = ~x, y = ~value, split = ~variable,
marker=list(color=~variable))
fig
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")