Estou tentando configurar o seguinte no Shiny:
- leia o arquivo de origem usando uma rotina de leitura personalizada
- processar dataframe e renderizar
- monitorar o arquivo de origem para alterações usando o verificador de alterações de arquivo personalizado: quando o arquivo de origem tiver sido alterado, repita 1 e 2
Como isso pode ser feito?
Com base em várias postagens, tenho tentado a sorte com reactivePoll
, pois isso parece ser o mais direto conceitualmente. Mas, dependendo da tentativa exata, estou tendo vários problemas, como checkFunc
não ser encontrado ou seu argumento de entrada não ser reconhecido.
De forma mais geral, ainda estou lutando para compreender as muitas maneiras pelas quais as variáveis podem ser tornadas reativas ( Vantagens de reativo vs. observe vs. observeEvent ) e como tudo isso se aplica à minha situação.
Abaixo, segue um código simplificado que esperamos que forneça a essência:
library(shiny)
library(tidyverse)
#---------create data-----------
#tibble
id=c('p1','p2','p3')
val=c(2,4,6)
my_data=tibble(id,val)
#csv
file_csv='test.csv'
write_csv(my_data,file_csv)
#my "checkFunc" routine (with input argument)
myFileCheck = function(input_path) {
if (file.exists(input_path))
file.info(input_path)$mtime[1]
else
""}
#test
tmp_time = myFileCheck(file_csv)
print(tmp_time)
#my read routine (with input argument)
myReadRoutine = function(input_path){
df = read_csv(input_path, id = 'my_source')
}
#test
tmp_df=myReadRoutine(file_csv)
print(tmp_df)
#----------shiny---------
#ui
ui = fluidPage(tableOutput('my_data'))
#server
server = function(input, output, session) {
#-----this part works---
#always read data upon launch
df_shiny=myReadRoutine(file_csv)
#some processing for display
df_shiny_display = reactive({df_shiny %>%
mutate(val2=val*10)})
#render
output$my_data = renderTable(df_shiny_display())
#-----this part doesn't----
#use custom file check function (with argument): if file has changed, use custom file reader
df_shiny = reactivePoll(1000, session, checkFunc = myFileCheck(file_csv), myReadRoutine(file_csv))
}
shinyApp(ui = ui,
server = server)
o principal problema no seu código é que você atribui df_shiny duas vezes com isto:
df_shiny=myReadRoutine(file_csv)
Isso é redundante porque reactivePoll já verifica a cada segundo se o arquivo existe e foi alterado. Você tem que imaginar reactivePoll como um pescador que joga sua vara de pescar a cada segundo. Reactive, por outro lado, só muda se algo dentro muda e depois atualiza. Então reactive é como uma geladeira que muda se algo dentro dela muda, e é por isso que df_shiny_display muda quando df_shiny é atualizado via reactivePull! Espero que faça sentido. Se você estiver interessado em quando os elementos disparam, você pode imprimir algo no console :)Código corrigido:
Compreendendo a reatividade
Reactive
: Cria dependências e recalcula sempre que suas dependências mudam. Use para valores que precisam ser usados em cálculos ou renderização downstream.observe
: Executa código para seus efeitos colaterais quando as dependências mudam. Use para ações como impressão, clique em botões, gravação de arquivo, ...observeEvent
: Semelhante a observar, mas dispara somente quando um evento específico ocorre.