r-Shiny:如何避免全局变量和ggplot一次一个观察的问题



我正在构建一个闪亮的应用程序,每隔30秒,reactivefilereader就会读取新数据,并通过附加到自应用程序开始运行以来积累的数据来进行处理(数据处理功能将现有聚合数据附加到新数据中,并返回一行(,然后ggplot会在图上绘制这一观察结果。它将用一条线连续地绘制观察结果。然而,我收到了这个错误消息,闪亮的应用程序上没有任何内容。

geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?

我的数据如下:

ts
Px
2020-03-13 17:15:19.000 23335.5

我在server函数之外有一个全局变量。请注意,下面不包含任何数据,因为闪亮的将每30秒读取一次数据。

ggprice   <-  ggplot() + scale_colour_manual(values=c(Px="black"))

该图通过以下方式更新,ts为数据。它将只包含一个观察结果。

ggprice   <<-    ggprice   + geom_line(aes(x=Index,y=Px,colour = "Px"),data=ts)

我该如何克服这一点?

更新:根据要求提供一个可复制的示例

下面有两个全局变量,我知道它们非常笨拙。

  1. 全局变量1-xts_bars_Agg,用于存储自应用程序开始运行以来所有处理的数据
  2. 全局变量2-ggprice。每一个新的观测值都通过geom_line(...)附加在这个全局变量上

如何进行优化?这里可以避免全局变量吗

# 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)

嗨,你可以尝试使用像这样的反应值

#   --- 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)

return(df_xts)
}
# UI
ui <- fluidPage(
#ggplot
mainPanel(
plotOutput(outputId = 'ggp')
)
)
# Define server logic
server <- function(input, output, session) {
rective_values <- reactiveValues(
xts_bars_Agg = tibble(),
ggprice = ggplot() +
scale_colour_manual(values=c(Price="black"))
)
# whereas xts_bars_Agg contains all the xts data with many rows
observe({
reactive_values$xts_bars_Agg = rbind.xts(xts_bars_Agg,df_update()) 
# *** 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 ?
})
observeEvent(reactive_values$xts_bars_Agg,{
df_xts_final = computeMagicalVal(reactive_values$xts_bars_Agg)
reactive_values$ggprice = reactive_values$ggprice + 
geom_line(aes(x=Index,y=Px,colour = "Price"),
data= df_xts_final)
})
df_update <- reactiveFileReader(intervalMillis = 10000,session=NULL,
filePath = "output.csv",
readFunc = data_processing)

output$ggp <- renderPlot({
reactive_values$ggprice
})
}
# Run the application 
shinyApp(ui = ui, server = server)

希望这能有所帮助!!