I am building a shiny application where every 30 secs, reactivefilereader reads in new data and process it by appending to data accumulated since the the app starts running (the data processing function append new data with existing aggregated data and returns one single row), and then ggplot will plot this single observation on the plot. And it will plot out the observations continuously with a line. However, I received this error message and nothing is being plotted on the shiny app.
geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?
My data is as follow:
ts
Px
2020-03-13 17:15:19.000 23335.5
I have the global variable outside the server function. Note that below doesn't contain any data because the shiny will read in the data every 30 seconds.
ggprice <- ggplot() + scale_colour_manual(values=c(Px="black"))
And the plot is updated through below and ts is the data. And it will contain ONLY one observation.
ggprice <<- ggprice + geom_line(aes(x=Index,y=Px,colour = "Px"),data=ts)
How do I overcome this ?
Update: A reproducible example as requested.
I have 2 global variables below, which i know are super clumsy.
- Global variable 1 -
xts_bars_Aggused to store all the processed data since the app starts running - Global variable 2 -
ggprice. Every new observation is appended on this global variable bygeom_line(...).
How can this be optimized ? Can the global variables be avoided here?
# Global variables
xts_bars_Agg <- NULL
# --- Function: Data I/O ------------------------------------------------------
data_processing <- function(csv_file){
df <- read.csv(csv_file, header=T,stringsAsFactors = F,colClasses = c("character","double"))
# convert String to timestamp, remove string timestamp
df <- (data.frame( Timestamp = strptime(df[,1],"%Y-%m-%d %H:%M:%OS"), df[,c(-1)]))
df_xts <- xts(x=df[,c(-1)], order.by=df$Timestamp)
xts_bars_Agg <<- rbind.xts(xts_bars_Agg,df_xts)
# *** the reason I need to rbind the new df_xts to
# existing xts_bars_agg (xts object)
# because the computeMagicalVal function below needs
# both the previous aggregated xts data plus the current xts data
# to compute a value.
# This and the usage of global variable looks very clumsy and inefficient and stupid to me.
# Is there a way to optimise this ?
df_xts_final <- computeMagicalVal(xts_bars_Agg)
# return df_xts_final with only one row,
# whereas xts_bars_Agg contains all the xts data with many rows
return(df_xts_final)
}
# second global variable
# global variable
ggprice <- ggplot() +
scale_colour_manual(values=c(Price="black"))
ggplot_func <- function(ts){
ggprice <<- ggprice + geom_line(aes(x=Index,y=Px,colour = "Price"),data=ts)
return(ggprice)
}
# UI
ui <- fluidPage(
#ggplot
mainPanel(
plotOutput(outputId = 'ggp')
)
)
# Define server logic
server <- function(input, output, session) {
df_update <- reactiveFileReader(intervalMillis = 10000,session=NULL,
filePath = "output.csv",
readFunc = data_processing)
output$ggp <- renderPlot({
ggplot_func(df_update())
})
}
# Run the application
shinyApp(ui = ui, server = server)