Reputation: 5907
I am working with the R programming language. I wrote the following code to make an interactive time series "slider"
library(dplyr)
library(ggplot2)
library(shiny)
library(plotly)
library(htmltools)
library(dplyr)
#generate data
set.seed(123)
var = rnorm(731, 100,25)
date= seq(as.Date("2014/1/1"), as.Date("2016/1/1"),by="day")
data = data.frame(var,date)
vals <- 90:100
combine <- vector('list', length(vals))
count <- 0
for (i in vals) {
data$var_i = i
data$new_var_i = ifelse(data$var >i,1,0)
#percent of observations greater than i (each month)
aggregate_i = data %>%
mutate(date = as.Date(date)) %>%
group_by(month = format(date, "%Y-%m")) %>%
summarise( mean = mean(new_var_i))
#combine files together
aggregate_i$var = i
aggregate_i$var = as.factor(aggregate_i$var)
count <- count + 1
combine[[count]] <- aggregate_i
}
result_1 <- bind_rows(combine)
result_1$group = "group_a"
result_1$group = as.factor(result_1$group)
######
var = rnorm(731, 85,25)
date= seq(as.Date("2014/1/1"), as.Date("2016/1/1"),by="day")
data = data.frame(var,date)
vals <- 90:100
combine <- vector('list', length(vals))
count <- 0
for (i in vals) {
data$var_i = i
data$new_var_i = ifelse(data$var >i,1,0)
#percent of observations greater than i (each month)
aggregate_i = data %>%
mutate(date = as.Date(date)) %>%
group_by(month = format(date, "%Y-%m")) %>%
summarise( mean = mean(new_var_i))
#combine files together
aggregate_i$var = i
aggregate_i$var = as.factor(aggregate_i$var)
count <- count + 1
combine[[count]] <- aggregate_i
}
result_2 <- bind_rows(combine)
result_2$group = "group_b"
result_2$group = as.factor(result_2$group)
#combine all files
final = rbind(result_1, result_2)
gg <-ggplot(final, aes(frame = var, color = group)) + geom_line(aes(x=month, y=mean, group=1))+ theme(axis.text.x = element_text(angle=90)) + ggtitle("title")
gg = ggplotly(gg)
From here, I want to make 3 additional graphs corresponding to the value of "var" where the slider is currently at. I have illustrated this below (for var = 90):
Here is the R code required to make these 3 additional graphs (for var = 90):
#### filter for var = 90
a90 = final %>%
filter(var == 90)
a90 = a90 %>%
group_by(group) %>%
summarise( avg = mean(mean))
##bar plot
plot<-ggplot(data=a90, aes(x=group, y=avg)) +
geom_bar(stat="identity") + ggtitle("bar plot")
bar_plotly <- ggplotly(plot)
#pie chart
Pie = ggplot(a90, aes(x="", y=(1-avg), fill=group)) +
geom_bar(stat="identity", width=1) +
coord_polar("y", start=0) +ggtitle( "Pie Chart") + scale_fill_brewer(palette="Blues")+
theme_minimal()
#for some reason this does not work
pie_plotly = ggplotly(Pie)
#table
fig <- plot_ly(
type = 'table',
columnwidth = c(100, 100),
columnorder = c(0, 1),
header = list(
values = c("average","group"),
align = c("center", "center"),
line = list(width = 1, color = 'black'),
fill = list(color = c("grey", "grey")),
font = list(family = "Arial", size = 14, color = "white")
),
cells = list(
values = rbind(a90$avg, a90$group),
align = c("center", "center"),
line = list(color = "black", width = 1),
font = list(family = "Arial", size = 12, color = c("black"))
))
fig
I tried to put all the graphs together but this did not work:
doc <- htmltools::tagList(
div(gg, style = "float:left;width:50%;"),
div(bar_plotly,style = "float:left;width:50%;"),
div(fig, style = "float:left;width:50%;"))
htmltools::save_html(html = doc, file = "final.html")
Error in as.vector(x, "character") :
cannot coerce type 'environment' to vector of type 'character'
Can someone please tell me if this is possible to update the other graphs as the user slides the slider for the first graph?
Thanks
> sessionInfo()
R version 4.0.3 (2020-10-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19041)
Matrix products: default
locale:
[1] LC_COLLATE=English_Canada.1252 LC_CTYPE=English_Canada.1252 LC_MONETARY=English_Canada.1252
[4] LC_NUMERIC=C LC_TIME=English_Canada.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] shiny_1.6.0 htmltools_0.5.1.1 dplyr_1.0.3 plotly_4.9.3 ggplot2_3.3.3
loaded via a namespace (and not attached):
[1] Rcpp_1.0.6 later_1.1.0.1 pillar_1.4.7 compiler_4.0.3 RColorBrewer_1.1-2 tools_4.0.3
[7] digest_0.6.27 jsonlite_1.7.2 lifecycle_0.2.0 tibble_3.0.5 gtable_0.3.0 viridisLite_0.3.0
[13] pkgconfig_2.0.3 rlang_0.4.10 cli_2.2.0 rstudioapi_0.13 crosstalk_1.1.1 yaml_2.2.1
[19] fastmap_1.1.0 withr_2.4.1 httr_1.4.2 generics_0.1.0 vctrs_0.3.6 htmlwidgets_1.5.3
[25] grid_4.0.3 tidyselect_1.1.0 glue_1.4.2 data.table_1.13.6 R6_2.5.0 fansi_0.4.2
[31] purrr_0.3.4 tidyr_1.1.2 farver_2.0.3 magrittr_2.0.1 promises_1.1.1 scales_1.1.1
[37] ellipsis_0.3.1 assertthat_0.2.1 xtable_1.8-4 mime_0.9 colorspace_2.0-0 httpuv_1.5.5
[43] labeling_0.4.2 lazyeval_0.2.2 munsell_0.5.0 crayon_1.3.4
Upvotes: 0
Views: 502
Reputation: 1236
According to plotly's tutorial, the way to combine different plots is to use subplot
. By doing this, it also links the slider to all plots if you defined the frame argument in all plots (see this other answer).
Also, for these more complicated plots, I think it is always safer to work directly in the plotly
API instead of converting a ggplot
# create summary dataframe for bar chart and pie chart
df.summary <- final %>% group_by(group, var) %>%
summarise( avg = mean(mean)) %>% ungroup()
# create line chart
gg <- final %>%
plot_ly(x = ~month, y = ~mean, frame=~var, color=~group, type = 'scatter', mode = 'lines', colors = 'Set1') %>%
layout(showlegend = F)
# create bar chart
bar_plotly <- df.summary %>%
plot_ly(x = ~group, y = ~avg, frame=~var, color=~group, ids=groups, type = 'bar', colors = 'Set1') %>%
layout(showlegend = F, yaxis = list(range = c(0, 0.7)))
# create pie chart
Pie <- df.summary %>%
plot_ly(values = ~avg, frame=~var, ids=groups, type = 'pie', domain = list(x = c(0.6, 1), y = c(0, 0.4)), colors = 'Set1') %>%
layout(showlegend = F)
# combine all of them into one interactive plot
subplot(gg, subplot(bar_plotly, Pie, nrows = 2), nrows = 1)
According to plotly, not all traces fully support animations. So the transitions in the pie chart will not be smooth.
Also, I don't think you can link the table with the current plotly API.
Another option would be to create a shiny application, where you could have more control.
Upvotes: 2