I have a simple application in shiny and I would like to add to the trend lines. I know how to add a linear trend line using the lm and abline functions in ggplot, but how do I add trend lines in R Using only Plotly.
library(shiny)
library(plotly)
library(shinyWidgets)
set.seed(666)
df1 <- data.frame(Date = rep(seq(as.Date("2020-01-03"), by="day", len=12),10,replace = TRUE),
Product = rep(LETTERS[1:10], each = 12),
Value = sample(c(0:300),120, replace = T))
ui <- fluidPage(
pickerInput("All", "Choose", multiple = F, choices = unique(df1$Product) ,
options = list(`max-options` = 4,size = 10)),
plotlyOutput('plot')
)
server <- function(input, output) {
trend<- reactive({
df1 %>%
filter(Product %in% input$All) %>%
arrange(Date) %>%
droplevels()
})
output$plot <- renderPlotly({
plot_ly(data=trend(), x=~Date, y = ~Value,
type = 'scatter', mode = 'lines+markers')
})
}
shinyApp(ui = ui, server = server)
How about adding a line using linear regression?
library(shiny)
library(plotly)
library(shinyWidgets)
set.seed(666)
df1 <- data.frame(Date = rep(seq(as.Date("2020-01-03"), by="day", len=12),10,replace = TRUE),
Product = rep(LETTERS[1:10], each = 12),
Value = sample(c(0:300),120, replace = T))
ui <- fluidPage(
pickerInput("All", "Choose", multiple = F, choices = unique(df1$Product) ,
options = list(`max-options` = 4,size = 10)),
plotlyOutput('plot')
)
server <- function(input, output) {
trend<- reactive({
df1 %>%
filter(Product %in% input$All) %>%
arrange(Date) %>%
droplevels()
})
output$plot <- renderPlotly({
t <- trend()
m <- lm(Value~Date,data = t)
p <-plot_ly(data=t, x=~Date, y = ~Value,
type = 'scatter', mode = 'lines+markers')
p = add_lines(p, x=~Date, y=predict(m), name="Linear")
})
}
shinyApp(ui = ui, server = server)
Related
In the relatively simple shiny application below I select a point on load. Once the user chooses a new number in the selector I'd like highcharter to select that point instead. In other words, if the user selects 1 then then it should select the 1st point.
Suggestions for how to do this?
library(shiny)
library(highcharter)
ui <- function(){
div(
selectInput('id', label = 'select', choices = 1:3, selected = 2),
highchartOutput("plot")
)
}
server <- function(session, input, output){
output$plot <- renderHighchart({
hc <- highchart() %>%
hc_chart(events = list(load = JS("function(){this.series[0].points[2].select()}"))) %>%
hc_add_series(data.frame(x = 1:3, y = 1:3), "scatter", hcaes(x, y)) %>%
hc_plotOptions(
allowPointSelect = TRUE
)
hc
})
observeEvent(input$id, {
# Here I'd like to send a message to the highchart
# to select the chosen point
})
}
shinyApp(ui, server)
This can be done using hcpxy_update_point function in the development version of {highcharter} (remotes::install_github("jbkunst/highcharter")).
Be sure to use the correct id for the chart which in this case is plot.
More examples in https://jbkunst.shinyapps.io/02-proxy-functions/.
library(shiny)
library(highcharter)
ui <- function(){
div(
selectInput('id', label = 'select', choices = 1:3, selected = 2),
highchartOutput("plot")
)
}
server <- function(session, input, output){
output$plot <- renderHighchart({
hc <- highchart() %>%
hc_chart(events = list(load = JS("function(){this.series[0].points[2].select()}"))) %>%
hc_add_series(
data.frame(x = 1:3, y = 1:3),
"scatter",
hcaes(x, y),
id = "someid",
) %>%
hc_plotOptions(
allowPointSelect = TRUE
)
hc
})
observeEvent(input$id, {
id_0_based <- as.numeric(input$id) - 1
highchartProxy("plot") %>%
# set all points unselected `selected = FALSE`
hcpxy_update_point(id = "someid", 0:2, selected = FALSE) %>%
# then set to selected the _selected_ point
hcpxy_update_point(
id = "someid",
id_point = id_0_based,
selected = TRUE
)
})
}
shinyApp(ui, server)
I have a application that has a reative table(based on 2 selectInputs) and a graph. The data for graph is taken from reactive table.
So both graph and table is using the same data. So while constructing a graph, can I observe what the table is having.
Or should I read the same table again in the graph?
I mean should we call head(iris,n = as.numeric(input$rows)) again twice below?
Example,
library(shiny)
library(DT)
library(rAmCharts)
ui <- fluidPage(
selectInput("rows","Rows",c(1:150)),
dataTableOutput("input_table"),
amChartsOutput("barplot",width = 750, height = 500)
)
server <- function(input, output, session) {
output$input_table <- renderDataTable({
new_iris <- head(iris,n = as.numeric(input$rows))
datatable(new_iris)
})
output$barplot <- renderAmCharts({
new_iris1 <- head(iris,n = as.numeric(input$rows)) ## should i call this again???????? Cannot we use from rendertable?
new_iris1 <- new_iris1 %>% group_by(Species) %>% summarise(total = sum(Petal.Length))
pipeR::pipeline(
amBarplot(
x = "Species",
y = "total",
ylab = "X",
xlab = "Y",
data = new_iris1,
labelRotation = 90
),
setChartCursor()
)
})
}
shinyApp(ui, server)
You may want to put your data object in a reactive expression so you can see what is being rendered, like so, this way you can access data() later on in your app
library(shiny)
library(DT)
library(dplyr)
library(rAmCharts)
ui <- fluidPage(
selectInput("rows","Rows",c(1:150)),
dataTableOutput("input_table"),
amChartsOutput("barplot",width = 750, height = 500)
)
server <- function(input, output, session) {
data <- eventReactive(input$rows,{
head(iris,n = as.numeric(input$rows))
})
output$input_table <- renderDataTable({
datatable(data())
})
output$barplot <- renderAmCharts({
new_iris1 <- data()
new_iris1 <- new_iris1 %>% group_by(Species) %>% summarise(total = sum(Petal.Length))
pipeR::pipeline(
amBarplot(
x = "Species",
y = "total",
ylab = "X",
xlab = "Y",
data = new_iris1,
labelRotation = 90
),
setChartCursor()
)
})
}
shinyApp(ui, server)
I would like to be able to select an item in the list by grouped names. Unfortunately, the group does not appear for a single name, as seen in the picture below. How can I change it?
My code:
library(plotly)
library(dplyr)
library(shiny)
library(shinyWidgets)
trend_pal <- c('red','blue', 'yellow', 'green') #Palette
TD <- data.frame(Name = rep(c("John Smith", "Antonio Gilbert", "Rickie Hooley", "John Marquez", "Christian Thompson", "Rickie Galvan", "John Anan", "Antonio Rossi")[1:8], each = 12),
Month = rep(month.abb[1:12],8,replace = TRUE),
Value = sample(c(0:300),96, replace = T), stringsAsFactors = F)
TD=as.tbl(TD)
output <- split(TD[,1], sub("\\s.*", " ", TD$Name))
for (i in seq_along(output)){
colnames(output[[i]]) <- ''
}
# UI
ui <- fluidPage(
pickerInput("All", "Choose", multiple = T,choices = c("Antonio" = unique(output$Antonio), 'Christian' = unique(output$Christian),
"John" = unique(output$John), 'Rickie' = unique(output$Rickie)),
options = list(`max-options` = 4,size = 10)),
plotlyOutput('plot')
)
# Server code
server <- function(input, output) {
output$plot <- renderPlotly({
#Filtering data based on user input
trend <- TD %>%
filter(Name %in% input$All) %>%
arrange(Month) %>%
droplevels()
#Plot
plot_ly(data=trend, x=~Month, y = ~Value,
type = 'scatter', mode = 'lines+markers',
color = ~Name , colors = trend_pal)
})
}
# Return a Shiny app object
shinyApp(ui = ui, server = server)
you can see this example option-groups-for-selectize-input, when you have just one name in your group, you have to set a list. in your case :
ui <- fluidPage(
pickerInput("All", "Choose", multiple = T,choices = c("Antonio" = unique(output$Antonio), 'Christian' = list(unique(output$Christian)),
"John" = unique(output$John), 'Rickie' = unique(output$Rickie)),
options = list(`max-options` = 4,size = 10)),
plotlyOutput('plot')
)
EDIT : to answer your comment
library(plotly)
library(dplyr)
library(shiny)
library(shinyWidgets)
trend_pal <- c('red','blue', 'yellow', 'green') #Palette
TD <- data.frame(Name = rep(c("John Smith", "Antonio Gilbert", "Rickie Hooley", "John Marquez", "Christian Thompson", "Rickie Galvan", "John Anan", "Antonio Rossi")[1:8], each = 12),
Month = rep(month.abb[1:12],8,replace = TRUE),
Value = sample(c(0:300),96, replace = T), stringsAsFactors = F)
output <- split(TD[,1], sub("\\s.*", "", TD$Name))
# creation of choices
choices <- lapply(output,function(x){
if(length(unique(x))>1){
unique(x)
} else{
list(unique(x))
}
})
# UI
ui <- fluidPage(
pickerInput("All", "Choose", multiple = T,choices = choices,
options = list(`max-options` = 4,size = 10)),
plotlyOutput('plot')
)
# Server code
server <- function(input, output) {
output$plot <- renderPlotly({
#Filtering data based on user input
trend <- TD %>%
filter(Name %in% input$All) %>%
arrange(Month) %>%
droplevels()
#Plot
plot_ly(data=trend, x=~Month, y = ~Value,
type = 'scatter', mode = 'lines+markers',
color = ~Name , colors = trend_pal)
})
}
# Return a Shiny app object
shinyApp(ui = ui, server = server)
I would like setting different color for each line on the chart. Currently, when I choose the same product from two lists I get the same colors on the chart. How can I set different colors for the same product from different years? Bellow my code and example plots:
library(plotly)
library(dplyr)
library(shiny)
library(shinyWidgets)
library(readxl)
library(tidyr)
df1 <- data.frame(Month = rep(month.abb[1:12],10,replace = TRUE), Product = rep(LETTERS[1:10], each = 12),
Value = sample(c(0:300),120, replace = T), stringsAsFactors = F)
df2 <- data.frame(Month = rep(month.abb[1:12],10,replace = TRUE), Product = rep(LETTERS[1:10], each = 12),
Value = sample(c(0:300),120, replace = T), stringsAsFactors = F)
trend_pal <- c('red','blue', 'yellow', 'green') #Palette
# UI
ui <- fluidPage(
column(
6,fluidRow(column(6, selectizeInput("All", "Year: 2018", multiple = T,choices = unique(df1$Product),
options = list(maxItems = 5, placeholder = 'Choose a product:'))),
column(6, selectizeInput("All2", "Year: 2019", multiple = T,choices = unique(df2$Product),
options = list(maxItems = 5, placeholder = 'Choose a product:'))))
),
column(
12,fluidRow(column(12, plotlyOutput('plot'))
)
)
)
# Server code
server <- function(input, output) {
outVar <- reactive({
df1 %>%
filter(Product %in% input$All) %>%
arrange(Month) %>%
droplevels()
})
outVar2 <- reactive({
df2 %>%
filter(Product %in% input$All2) %>%
arrange(Month) %>%
droplevels()
})
output$plot <- renderPlotly({
plot_ly(data=outVar(), x=~Month, y = ~Value,
type = 'scatter', mode = 'lines', legendgroup = "1",
color = ~Product , colors = trend_pal) %>%
add_trace(data=outVar2(), x=~Month, y = ~Value,
type = 'scatter', mode = 'lines', legendgroup = "2",
color = ~Product , colors = "Dark2") %>%
layout(legend = list(orientation = 'h'))
})
}
# Return a Shiny app object
shinyApp(ui = ui, server = server)
A very naive trick. I added space to the product in the second column. That does the different coloring. Thanks for the reproducible example.
library(plotly)
library(dplyr)
library(shiny)
library(shinyWidgets)
library(readxl)
library(tidyr)
df1 <- data.frame(Month = rep(month.abb[1:12],10,replace = TRUE), Product = rep(LETTERS[1:10], each = 12),
Value = sample(c(0:300),120, replace = T), stringsAsFactors = F)
df2 <- data.frame(Month = rep(month.abb[1:12],10,replace = TRUE), Product = rep(LETTERS[1:10], each = 12),
Value = sample(c(0:300),120, replace = T), stringsAsFactors = F)
df2$Product <- paste0(" ",df2$Product)
trend_pal <- c('red','blue', 'yellow', 'green') #Palette
trend_pal2 <- c('cyan','magenta', 'black', 'orange') #Palette2
# UI
ui <- fluidPage(
column(
6,fluidRow(column(6, selectizeInput("All", "Year: 2018", multiple = T,choices = unique(df1$Product),
options = list(maxItems = 5, placeholder = 'Choose a product:'))),
column(6, selectizeInput("All2", "Year: 2019", multiple = T,choices = unique(df2$Product),
options = list(maxItems = 5, placeholder = 'Choose a product:'))))
),
column(
12,fluidRow(column(12, plotlyOutput('plot'))
)
)
)
# Server code
server <- function(input, output) {
outVar <- reactive({
df1 %>%
filter(Product %in% input$All) %>%
arrange(Month) %>%
droplevels()
})
outVar2 <- reactive({
df2 %>%
filter(Product %in% input$All2) %>%
arrange(Month) %>%
droplevels() %>%
mutate(year = 2019)
})
output$plot <- renderPlotly({
plot_ly(data=outVar(), x=~Month, y = ~Value,
type = 'scatter', mode = 'lines', legendgroup = "1",
color = ~Product , colors = trend_pal) %>%
add_trace(data=outVar2(), x=~Month, y = ~Value,
type = 'scatter', mode = 'lines', legendgroup = "2",
color = ~Product ,
colors = trend_pal2) %>%
layout(legend = list(orientation = 'h'))
})
}
# Return a Shiny app object
shinyApp(ui = ui, server = server)
Please run this script below, the following R script gives a shiny dashboard with two boxes. I want to reduce the width between two boxes and display data in the right chart. The data should be based on the on click event that we see in the ggplotly function. Also plotly can be used to do the job, I guess. I want the code to fast and efficient at the same time.
## app.R ##
library(shiny)
library(shinydashboard)
library(bupaR)
library(eventdataR)
library(lubridate)
library(dplyr)
library(XML)
library(edeaR)
library(xml2)
library(data.table)
library(ggplot2)
library(ggthemes)
library(glue)
library(tibble)
library(miniUI)
library(tidyr)
library(shinyTime)
library(magrittr)
library(plotly)
library(DT)
library(splitstackshape)
library(scales)
patients$patient = as.character(patients$patient)
a1 = patients$patient
a2 = patients$handling
a3 = patients$time
a123 = data.frame(a1,a2,a3)
patients_eventlog = simple_eventlog(a123, case_id = "a1",activity_id = "a2",
timestamp = "a3")
dta <- reactive({
tr <- data.frame(traces(patients_eventlog, output_traces = T, output_cases =
F))
tr.df <- cSplit(tr, "trace", ",")
tr.df$af_percent <-
percent(tr.df$absolute_frequency/sum(tr.df$absolute_frequency))
pos <- c(1,4:ncol(tr.df))
tr.df <- tr.df[,..pos]
tr.df <- melt(tr.df, id.vars = c("trace_id","af_percent"))
tr.df
})
patients10 <- reactive({
patients11 <- arrange(patients_eventlog, a1)
patients12 <- patients11 %>% arrange(a1, a2,a3)
patients12 %>%
group_by(a1) %>%
mutate(time = as.POSIXct( a2, format = "%m/%d/%Y %H:%M"),diff_in_sec = a2 -
lag( a2)) %>%
mutate(diff_in_sec = ifelse(is.na(diff_in_sec),0,diff_in_sec)) %>%
mutate(diff_in_hours = as.numeric(diff_in_sec/3600)) %>%
mutate(diff_in_days = as.numeric(diff_in_hours/24))
})
ui <- dashboardPage(
dashboardHeader(title = "Trace Chart"),
dashboardSidebar(
width = 0
),
dashboardBody(
box(title = "Trace Chart", status = "primary",height = "455" ,solidHeader =
T,
plotlyOutput("trace_plot"),style = "height:420px; overflow-y:
scroll;overflow-x: scroll;"),
box( title = "Trace Summary", status = "primary", height = "455",solidHeader
= T,
dataTableOutput("trace_table"))
)
)
server <- function(input, output)
{
output$trace_plot <- renderPlotly({
mp1 = ggplot(data = dta(), aes(x = variable,y = trace_id, fill = value,
label = value,
text=paste("Variable:",variable,"<br> Trace
ID:",trace_id,"<br>
Value:",value,"<br> Actuals:",af_percent))) +
geom_tile(colour = "white") +
geom_text(colour = "white", fontface = "bold", size = 2) +
scale_fill_discrete(na.value="transparent") +
theme(legend.position="none") + labs(x = "Traces", y = "Activities")
ggplotly(mp1, tooltip=c("text"), height = 1226, width = 1205)
})
output$trace_table <- renderDataTable({
req(event_data("plotly_click"))
Values <- dta() %>%
filter(trace_id == event_data("plotly_click")[["y"]]) %>%
select(value)
valueText <- paste0(Values[[1]] %>% na.omit(),collapse = "")
agg <- aggregate(a3~a1, data = patients10(), FUN = function(y){paste0(unique(y),collapse = "")})
currentPatient <- agg$a1[agg$a3 == valueText]
patients10_final <- patients10() %>%
filter(a1 %in% currentPatient)
datatable(patients10_final, options = list(paging = FALSE, searching = FALSE))
})
}
shinyApp(ui, server)
I have created an easy example how You can use coupled events from plotly with some sample data that is close to Your needs:
library(shiny)
library(plotly)
library(DT)
set.seed(100)
data <- data.frame(A=sample(c('a1','a2','a3'),10,replace=T),
B=1:10,
C=11:20,
D=21:30)
shinyApp(
ui = fluidPage(
plotlyOutput("trace_plot"),
DT::dataTableOutput('tbl')),
server = function(input, output) {
output$trace_plot <- renderPlotly({
plot_ly(data, x=~A,y=~B,z=~C, source = "subset") %>% add_histogram2d()})
output$tbl <- renderDataTable({
event.data <- event_data("plotly_click", source = "subset")
if(is.null(event.data) == T) return(NULL)
print(event.data[ ,c(3:4)])
})
}
)
As You can see by pressing on the first plot we get the subset of data below in the table (x and y values), further you can use it to merge with the primary data to display timestamps etc. .