R Plotly Add Trace within Loop - r

I have an issue with using loops to add trace in plotly, though I have no idea what the cause is.
If I try to make a plot using the method for P below, only the data for last column (HORSE) is shown. Rabbit and Dog still show up, but both display values for Horse.
If, however, I use the P1 method the graph works perfectly. I would really like to be able to do this within a loop as the length of columns varies.
df <- data.frame(AGE = c(0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5),
YEAR = c(2010,2011,2012,2013,2014,2015,2016,2017,2010,2011,2012,2013,2014,2015,2016,2017,2010,2011,2012,2013,2014,2015,2016,2017,2010,2011,2012,2013,2014,2015,2016,2017,2010,2011,2012,2013,2014,2015,2016,2017,2010,2011,2012,2013,2014,2015,2016,2017),
RABBIT = c(0,5,2,6,8,5,8,4,3,6,2,7,5,5,9,9,1,4,4,6,5,3,7,7,6,8,2,6,9,1,9,1,1,2,10,1,10,10,4,2,4,8,7,0,3,4,5,7),
DOG = c(2,5,0,8,2,5,9,5,10,5,10,3,8,9,2,7,5,1,1,4,6,7,7,0,6,5,7,2,2,9,4,2,6,0,7,1,7,6,9,9,9,5,5,9,0,9,10,2),
HORSE = c(7,1,9,10,6,6,5,1,4,5,0,3,0,3,2,4,3,6,1,9,6,4,3,1,7,8,4,1,8,6,5,9,2,0,5,5,6,1,1,7,4,9,5,0,8,1,5,7)
)
L <- c("RABBIT","DOG","HORSE")
P <- plot_ly(data = df)
for(i in 1:length(L)){
P<-add_trace(P, y=~df[[L[i]]], x=~df$AGE, frame =~df$YEAR, type="scatter", mode="lines", name = L[i])
}
P1 <- plot_ly(data = df)
P1 <- add_trace(P1, y=~df[[L[1]]], x=~df$AGE, frame =~df$YEAR, type="scatter", mode="lines", name = L[1])
P1 <- add_trace(P1, y=~df[[L[2]]], x=~df$AGE, frame =~df$YEAR, type="scatter", mode="lines", name = L[2])
P1 <- add_trace(P1, y=~df[[L[3]]], x=~df$AGE, frame =~df$YEAR, type="scatter", mode="lines", name = L[3])
P
P1

You can use this solution:
P <- plot_ly(data = df)
for(k in 1:length(L)) {
dfk <- data.frame(y=df[[L[k]]], AGE=df$AGE, YEAR=df$YEAR)
P <- add_trace(P, y=~y, x=~AGE, frame =~YEAR, data=dfk,
type="scatter", mode="lines", name = L[k])
}

Related

Plotly: How to set background color per data

I want to set two different colors as the plot background: one color per data like this
Here are my plots so far:
The following suggestion is a minimal reproducible example to show you that it can be done. Albeit not so easily and elegantly as you may have hoped. To my knowledge, there does not yet exist a way to alternate backround colors without doing so through shapes. The following setup at least captures some of the features of your demonstrated setup, in that it is a mix of a line and a bar chart, and that it produces multiple subplots in one go.
Plot:
Code:
library(dplyr)
library(plotly)
df = data.frame(x=c(1,2,3,4,5,6,7,8,9,10,11,12),
y1=c(4,2,4,2,6,7,8,7,9,10,9,12),
y2=c(3,4,5,6,3,1,5,6,3,2,7,8))
list(df$x)
x_start <- df$x[seq(1, length(df$x), 2)]
x_stops <- df$x[seq(2, length(df$x), 2)]
p1 <- plot_ly(x=df$x, y=df$y1, mode='lines', line=list(color='green'), name = 'line')
p2 <- plot_ly(df) %>% add_bars(x=~x, y=~y2, name='bar', width=0.4)
# set up shapes
shape=list(type='rect', line = list(color = 'rgba(0,0,0,0)'), fillcolor="rgba(147,112,219,0.1)", xref='x', yref='y')
shape_offset = 0.5
shapes <- list()
for (i in seq_along(x_start)){
print(i)
shape[["x0"]] <- x_start[i] + shape_offset
shape[["x1"]] <- x_stops[i] + shape_offset
shape[["y0"]] <- 0
shape[["y1"]] <- 16
shapes <- c(shapes, list(shape))
}
p1 <- layout(p1, shapes=shapes, xaxis = list(showgrid=FALSE))
p2 <- layout(p2, shapes=shapes)
p <- subplot(p1, p2, nrows = 2, margin=0.05)
p
I hope this will be useful to you. If you'd like we can discuss further details when you've had a chance to look at it.
Edit 1:
Here's a suggestion that takes the max of y into consideration when the background shapes are built. This can be made flexible with regards to the number of subplots if you're interested.
Plot 2:
Code 2:
library(dplyr)
library(plotly)
df = data.frame(x=c(1,2,3,4,5,6,7,8,9,10,11,12),
y1=c(4,2,4,2,6,7,8,7,9,10,9,12),
y2=c(3,4,5,6,3,1,5,6,3,2,7,8))
list(df$x)
x_start <- df$x[seq(1, length(df$x), 2)]
x_stops <- df$x[seq(2, length(df$x), 2)]
p1 <- plot_ly(x=df$x, y=df$y1, mode='lines', line=list(color='green'), name = 'line')
p2 <- plot_ly(df) %>% add_bars(x=~x, y=~y2, name='bar', width=0.4)
# set up plot 1 shapes
shape=list(type='rect', line = list(color = 'rgba(0,0,0,0)'), fillcolor="rgba(147,112,219,0.1)", xref='x', yref='y')
shape_offset = 0.5
shapes <- list()
for (i in seq_along(x_start)){
print(i)
shape[["x0"]] <- x_start[i] + shape_offset
shape[["x1"]] <- x_stops[i] + shape_offset
shape[["y0"]] <- 0
shape[["y1"]] <- max(df$y1)
shapes <- c(shapes, list(shape))
#print()
}
# set up plot 2 shapes
shape2=list(type='rect', line = list(color = 'rgba(0,0,0,0)'), fillcolor="rgba(147,112,219,0.1)", xref='x', yref='y')
shape2_offset = 0.5
shapes2 <- list()
for (i in seq_along(x_start)){
print(i)
shape2[["x0"]] <- x_start[i] + shape2_offset
shape2[["x1"]] <- x_stops[i] + shape2_offset
shape2[["y0"]] <- 0
shape2[["y1"]] <- max(df$y2)
shapes2 <- c(shapes2, list(shape2))
#print()
}
p1 <- layout(p1, shapes=shapes, xaxis = list(showgrid=FALSE))
p2 <- layout(p2, shapes=shapes2)
p <- subplot(p1, p2, nrows = 2, margin=0.05)
p

How to make many plotly charts each one in its own Viewer window?

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?

R Plotly - Plotting Multiple Regression Lines

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

R plotly Issues with hovering text in a trace loop

Following this post and this answer I have an additional question:
library(plotly)
# Create data
dat=data.frame(group = factor(rep(LETTERS[1:4], each=10)), my_x = rep(1:10, 4), my_y = rnorm(40))
str(dat)
# Let's do a first plot
p<-plot_ly(dat)
# Add a trace for each group using a loop
for(i in 1:length(levels(dat$group))){
subs <- subset(dat, group == levels(dat$group)[i])
p<-add_trace(p = p,
data = subs,
y=~my_y,
x=~my_x ,
name=levels(dat$group)[i],
type="scatter",
mode="markers+lines",
hoverinfo="text",
text=~paste0(levels(dat$group)[i], ": x=", round(my_x, 2), "y=", round(my_y, 2)))
}
p
Can anybody tell me why it is that when I hover over the data points, each of the labels shows the correct x and y values, however, they are all labelled as 'D:', while the legend shows the lines resemble A, B, C & D. I would like the hover text to be labeled correctly.
It could be an issue with the use of ~ in text. Try by creating the 'text' using the 'subs' data separately and then pass it on the add_trace
p <- plot_ly()
lvls <- levels(dat$group)
for(i in seq_along(lvls)){
subs <- droplevels(subset(dat, group == lvls[i]))
text1 <- with(subs, paste0(lvls[i], ": x=", round(my_x, 2), "y=", round(my_y, 2)))
p <- add_trace(p,
data = subs,
x = ~my_x,
y = ~my_y,
name = lvls[i],
type = 'scatter',
mode = 'markers+lines',
hoverinfo='text',
text=text1)
}
p
-output

Add multiple lines to a plot_ly graph with add_trace

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

Resources