Assuming I have a time series of multiple different cells, which I can split according to if they received a treatment or not - how can I plot all individual time series (without averaging) but group them according to the treatment in plotly?
It works perfectly with ggplot - and I know I can use ggplotly from there - but is there a full plotly way?
Here are some dummy data:
library("dplyr")
library("plotly")
cell <- c(rep("a", 10), rep("b", 10), rep("c", 10), rep("d", 10), rep("e", 10), rep("f", 10))
group <- c(rep("Untreated", 10), rep("Treated", 30), rep("Unknown", 20))
time <- rep(1:10, times=6)
value <- c(runif(60))
df <- data.frame(cell, group, time, value)
# I want this in plotly:
ggplot(df, aes(x=time, y=value, group=cell, color=group)) +
geom_line()
# For many "cells" this will explode the legend (my real data have hundreds of cells)
plot_ly(df, x=~time, y=~value, split=~cell, color=~group,
type="scatter", mode="line")
# This works but it connects the last and the first timepoint
plot_ly(df, x=~time, y=~value, group=~cell, color=~group,
type="scatter", mode="line")
But plotly gives me this (too many legendgroups for many cells):
Or this (it connects start and end of individual cells):
Is there any way plotly can do it - or do I need to use ggplotly?
Edit:
You can use legendgroup
and hide the duplicated trace names via showlegend
.
Also see: https://plotly.com/r/legend/#grouped-legend
Edit: After @JulianStopp modified the example data:
Here is a generalized approach to find the traces to hide in the legend. Sorry for switching to data.table
but I'm not familiar with dplyr
:
library(data.table)
library(plotly)
cell <- c(rep("a", 10), rep("b", 10), rep("c", 10), rep("d", 10), rep("e", 10), rep("f", 10))
group <- c(rep("Untreated", 10), rep("Treated", 30), rep("Unknown", 20))
time <- rep(1:10, times=6)
value <- c(runif(60))
DF <- data.frame(cell, group, time, value)
setDT(DF)
setorder(DF, group, cell, time)
DF[, rleid := rleid(get("cell")), by = "group"][, showlegend := fifelse(rleid == 1L, yes = TRUE, no = FALSE)]
DF[, trace_index := .GRP, by = .(group, cell)] # create trace indices
p <- plot_ly(DF, x=~time, y=~value, split=~cell, legendgroup = ~group, name = ~group, color = ~group,
type="scatter", mode="line") %>% style(showlegend = FALSE, traces = unique(DF[showlegend == FALSE, trace_index]))
print(p)
Initial answer:
library("dplyr")
library("plotly")
cell <- c(rep("a", 10), rep("b", 10), rep("c", 10))
group <- c(rep("Untreated", 10), rep("Treated", 20))
time <- c(seq(1:10), seq(1:10), seq(1:10))
value <- c(runif(30))
df <- data.frame(cell, group, time, value)
plot_ly(df, x=~time, y=~value, split=~cell, legendgroup = ~group, name = ~group, color = ~group,
type="scatter", mode="line") %>% style(showlegend = FALSE, traces = 2)