Trying to understand shiny reactive sliders

I am not going to show the whole code because it is rather lengthy. I am having a particular problem getting a filter to be reactive. So I am probably not doing it correctly in reactive mode. The code works in static mode. When I am in reactive mode the page displays but it is blank except for the title. When I take the server portion of the code out everything displays even the graph.
What I am trying to accomplish is filtering the ends of the pulse data because it is nothing by noise.

...
#from the UI
sliderInput("range", "Range:",
min = 1, max = 2000,
value = c(100,500))

#From the server

output$SC120C<- renderTable( { #there is leading and trailing data that must removed from the data frame for better resolution
filter( time_ns > input$range[1] & time_ns< input$range[2])%>%
select(time_ns, Channel2_Average, Channel2_Voltage)

})
THanks

At first glance, I think using the variable time_ns in the select statement may cause the issue that your filter may not be applied. However, for a better analysis can you please prepare a small code example with some sample data. That would be very helpful.

Best regards
Sebastian

I have been working on this most of the day and have it down to this and not sure where to go.
The last error(s) that I get is on the display of the shinyApp with SC120C not found.
I am positive the paths are correct and so are the file names. This code was originally written in as nonshiny script and it works exactly as expected. I am have only been coding for about 3 weeks so I know my code is clunky and amateurish but I have to start somewhere. This app is only on my computer so its not going out on the web its just for me to move the graphs back and forth to overlay them which I need to figure out how to get the timeoffset into the time_ns caculation too but that's another day.

library(shiny)
library(stringr)
library(dplyr)
library(ggplot2)
library(zoo)
library(DT)
library(tokenizers)
setwd ("E:/Updated_Datasets_20190603/SC106/")
datasets1 <- list("DS01", "DS02","DS03","DS04", "DS05", "DS06", "DS07", "DS08", "DS09", "DS10", "DS11",
                  "DS12", "DS13", "DS14" )
datasets2 <- list("Pulser_DS1", "Pulser_DS2",
                  "Pulser_DS3","Pulser_DS4", "Pulser_DS5", "Pulser_DS6", "Pulser_DS7", 
                  "Pulser_DS8", "Pulser_DS9", "Pulser_DS10", "Pulser_DS11",
                  "Pulser_DS12", "Pulser_DS13", "Pulser_DS14" )
ui <-fluidPage(
  
  titlePanel (title= h4("Display of the Data Set vs LTSpice Simulation")),
  
  sidebarLayout(
    sidebarPanel(
      
      selectInput( inputId = "dataset1", label= "1. Choose a DataSet for analysis:", choices = c(datasets1 )),
      
      selectInput( inputId = "dataset2", label= "2. Choose Pulser Dataset for analysis:", choices = c(datasets2 )),
      sliderInput("timeOffset", "TimeOffset", min=-500, max= 500,
                  value = 0, step = 100),
      
      # Input: Specification of range within an interval ----
      sliderInput("range", "Range:",
                  min = 1, max = 1000,
                  value = c(200,500))
    ),
    mainPanel(
      plotOutput ("myplot")
      
    )
  )
  
)

server <- function(input, output){
  
SC120000 <- renderTable({
    req(input$dataset1)
    SC120000[[input$dataset1]]
  




SC120 <-as.data.frame(SC120000)

SC120C <-SC120%>%
  mutate(time_ns = ((Time)*(1.0e9)))

# The Pulser is on channel of SC120 the other correction factors are commented out as they are needed for
#other SCopes and matrix data




SC120C %>%
  summarise(matrixCh1Datacf <- mean(Channel1_Voltage), # The correction factor for theMatrix Data Channel Pulser voltage if needed
            matrixCh2Datacf <- mean(Channel2_Voltage),
            
            tenPecentminch1voltage <- (0.10*min(Channel1_Voltage)), # calculate rise 10% min
            ninetyPercentmaxch1voltage <- (0.90*max(Channel1_Voltage)),
            
            tenPecentminch1voltage <- (0.10*min(Channel2_Voltage)), # calculate rise 10% min
            ninetyPercentmaxch1voltage <- (0.90*max(Channel2_Voltage)),      #Calculate rise time 90% max
            matrixCH1dT <<- (time_ns[2]-time_ns[1])*1000)


# The corrected Ch1 voltage


Channel2_Average<-as.vector( rollapply(SC120000$Channel2_Voltage, FUN= mean, width=18, na.rm=FALSE))
# a rolling average for smoothing the graph

Channel2_Average=append(Channel2_Average, c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), after= length(1))
# Some of the values are lost when rolling average is applied added back for concatinating vector to datafram
Channel2_Average[1] <- 0
Channel2_Average<-as.data.frame(Channel2_Average)
Channel2_Average <-cbind(SC120000$time_ns, Channel2_Average)

colnames(Channel2_Average)[1] <- "time_ns"


SC120C<- inner_join(Channel2_Average,SC120C) # this joins the frames

SC120C <-as.data.frame(SC120C)

})


Pulser <- renderTable({
  req(input$dataset2)
  Pulser[[input$dataset2]]
  
  
  
PulserC <-as.data.frame(Pulser)
colnames(Pulserc) <- c("Time", "Voltage") #naming columns 1 and 2 in Pulser1


PulserD <- PulserC %>%
  mutate(time_ns = ((Time)*(1.0e9))) #dplyr converts time to nanosec


colnames(PulserD)[3] <- "time_ns"
# Pulserfile <- Pulserfile %>% mutate(Voltage = ((Voltage)*1.5))

#dplyr converts time to nanosec


PulserD %>%
  summarise(
    
    
    LTSpicedatacf <- (mean(Voltage)), # The correction factor for the LTSPICE Pulser voltage
    tenPecentminLTSPICEvoltage <- (0.10*min(Voltage)),  # 10% of the minimum voltage
    ninetyPercentmaxLTSPICEvoltage <- (0.90*max(Voltage)), # 90% of the max voltage
    LTspicePulserdT <- (time_ns[2]-time_ns[1])*1000  # change in time for first row to second
    
  )


#Pulser Correction factor

PulserD <-PulserD %>%
  mutate(LTspice_Corrected =(Voltage-LTSpicedatacf))  # The corrected LTSpice votage which must be o

# plots graph of Pulser 4.1 LTSpice raw data
})

#Pulser <- Pulser   %>%   #there is leading and trailing data that must removed from the data frame for better resolution
#  filter( time_ns > 0 ) %>%
#  select ( Voltage,time_ns, LTspice_Corrected)

#SC120000<- SC120000%>% #there is leading and trailing data that must removed from the data frame for better resolution
#  filter( time_ns > 0 & time_ns<  2200)%>%
 #   select(time_ns, Channel2_Average, Channel2_Voltage)
  


output$myplot<-renderPlot({
  myplot<- ggplot() +
    
    geom_line(data=SC120C, aes(x=time_ns, y=Channel2_Average), na.rm = TRUE)+
    geom_line(data=PulserD, aes(x=time_ns, y= LTspice_Corrected))+
    theme_bw()
  print (myplot)
})
}
shinyApp(ui,server)

`````r

Hi,

Among other issues, the code does not run properly as there seems to be a dataset missing... (SC120000 ??)

Please provide an extract of this dataset that can be used to test the code like so:

SC120000 = data.frame(var1 = 1:10, var2 = letters[1:10])

To test if we could run your code as you do, clear all objects from workspace in the environment in R studio, then run the code (this prevents local variables to be used if not present in app itself)

Good luck

I have decided to rewrite most of the code to make it less circular
but I am still having trouble getting the DS and Pulserfiles into a dataframe from calling them
I do not get any errors and the App builds with this portion of code

library(shiny)
library(stringr)
library(dplyr)
library(ggplot2)
library(zoo)

library(tokenizers)
setwd("D:/Updated_Datasets_20190603/SC106")
datasets1 <- list("Select File", "DS01", "DS02","DS03","DS04", "DS05", "DS06", "DS07", "DS08", "DS09", "DS10", "DS11",
                  "DS12", "DS13", "DS14" )
datasets2 <- list("Select File"," Pulser_DS1", "Pulser_DS2",
                  "Pulser_DS3","Pulser_DS4", "Pulser_DS5", "Pulser_DS6", "Pulser_DS7",
                  "Pulser_DS8", "Pulser_DS9", "Pulser_DS10", "Pulser_DS11",
                  "Pulser_DS12", "Pulser_DS13", "Pulser_DS14" )
ui <-fluidPage(

  titlePanel (title= h1("Display of the Data Set vs LTSpice Simulation")),

  sidebarLayout(
    sidebarPanel(

      selectInput( inputId = "dataset1", label= "1. Choose a DataSet for analysis:", choices = c(datasets1 )),

      selectInput( inputId = "dataset2", label= "2. Choose Pulser Dataset for analysis:", choices = c(datasets2 )),
      sliderInput("timeOffset", "TimeOffset", min=-500, max= 500,
                  value = 0, step = 100),

      # Input: Specification of range within an interval ----
      sliderInput("range", "Range:",
                  min = 1, max = 1000,
                  value = c(200,500))
    ),
    mainPanel(
      plotOutput ("myplot")

    )
  )

)
server<-function(output, input)({ #beginning of server

  DS<-reactive(

        observe({
            if((input$dataset1)=="Select File") {
                 return()
       } else {
       DS<- read.delim(file=input$dataset1, pattern=".txt" , sep="," )
             }
        })
              )


Pulserfile<-reactive(
          observe({
          if((input$dataset2)=="Select File") {
            return()
          } else {
            Pulserfile<- read.delim(file=input$dataset2, pattern=".txt")


          }

          }) # end of pulser observe function

)

}) # end of server  function
shinyApp(ui,server)

but when I add

colnames(DS) <-c("Time", "Channel1_Voltage","Channel2_Voltage", "Channel3_Voltage","Channel4_Voltage")
colnames(Pulserfile) <-c("Time", "Voltage")

it gives me this error

runApp('D:/Pulserdataset/R/Bettershiny.R')

Listening on http://127.0.0.1:7230
Warning: Error in $: object of type 'closure' is not subsettable
47: server [D:/Pulserdataset/R/Bettershiny.R#69]
Error in DS$Time : object of type 'closure' is not subsettable

runApp('D:/Pulserdataset/R/Bettershiny.R')

Listening on http://127.0.0.1:7230
Warning: Error in $: object of type 'closure' is not subsettable
47: server [D:/Pulserdataset/R/Bettershiny.R#69]
Error in DS$Time : object of type 'closure' is not subsettable

runApp('D:/Pulserdataset/R/Bettershiny.R')

Listening on http://127.0.0.1:7230
Warning: Error in $: object of type 'closure' is not subsettable
47: server [D:/Pulserdataset/R/Bettershiny.R#69]
Error in DS$Time : object of type 'closure' is not subsettable

runApp('D:/Pulserdataset/R/Bettershiny.R')

Warning: Error in colnames<-: attempt to set 'colnames' on an object with less than two dimensions
49: stop
48: colnames<-
47: server [D:/Pulserdataset/R/Bettershiny.R#68]
Error in colnames<-(*tmp*, value = c("Time", "Channel1_Voltage", "Channel2_Voltage", :
attempt to set 'colnames' on an object with less than two dimensions

Hi,

Learning Shiny is tricky, especially the reactivity. Don't worry you'll get the hang of it :slight_smile:
I still didn't have access to the files, but make sure they all are in the Shiny App folder!

Then run this:

library(shiny)
library(stringr)
library(dplyr)
library(ggplot2)
library(zoo)
library(tokenizers)


ui <-fluidPage(
  
  titlePanel (title= h1("Display of the Data Set vs LTSpice Simulation")),
  
  sidebarLayout(
    sidebarPanel(
      
      selectInput( inputId = "selectDataset1", label= "1. Choose a DataSet for analysis:", choices = ""),
      
      selectInput( inputId = "selectDataset2", label= "2. Choose Pulser Dataset for analysis:", choices = ""),
      sliderInput("timeOffset", "TimeOffset", min=-500, max= 500,
                  value = 0, step = 100),
      
      # Input: Specification of range within an interval ----
      sliderInput("range", "Range:",
                  min = 1, max = 1000,
                  value = c(200,500))
    ),
    mainPanel(
      plotOutput ("myPlot"),
      plotOutput ("myTable")
      
    )
  )
  
)

server<-function(input, output, session)({ #beginning of server
  
  
  datasets1 <- list("DS01", "DS02","DS03","DS04", "DS05", "DS06", "DS07", "DS08", "DS09", "DS10", "DS11",
                    "DS12", "DS13", "DS14" )
  
  # You can use list.files() function to actually get the names of all files in a (sub)folder, and filter for .txt
  # datasets1 <- list.files(pattern = ".txt")
  
  datasets2 <- list("Pulser_DS1", "Pulser_DS2",
                    "Pulser_DS3","Pulser_DS4", "Pulser_DS5", "Pulser_DS6", "Pulser_DS7",
                    "Pulser_DS8", "Pulser_DS9", "Pulser_DS10", "Pulser_DS11",
                    "Pulser_DS12", "Pulser_DS13", "Pulser_DS14" )
  
  #Use updateSelectInput input to update names on the go (better than defining on top)
  updateSelectInput(session, "selectDataset1", choices = datasets1)
  updateSelectInput(session, "selectDataset2", choices = datasets2)
  
  DS = reactive({
    #read.delim assumes the files are in the app (sub)folder (must be for Shiny to work properly)
    myFile = read.delim(file=paste(input$selectDataset1, ".txt", sep = ""))
    colnames(myFile) = c("Time", "Channel1_Voltage","Channel2_Voltage", "Channel3_Voltage","Channel4_Voltage")
    myFile
  })
  
  Pulserfile = reactive({
    myFile = read.delim(file=paste(input$selectDataset2, ".txt", sep = ""))
    colnames(myFile) = c("Time", "Voltage")
    myFile
  })
  
  output$myPlot = renderPlot({
    
  })
  
  output$myTable = renderTable({
    DS()[1:5,] #To call a reactive dataframe, put () behind the name, but treat the rest of the code as usual
  })
  
  
}) # end of server  function


shinyApp(ui,server)

Good luck
PJ

Thnak you for your help. I guess I don't understand the session argument. I have watched server tutorials from the one on R studios and the one from Martin Hadley in lynda.com and neither talk about that argument. Is there any documentation or videos that could fill in that knowledge gap?

Hi,

I'm by no means an expert in this matter, but let me try and give you an intuitive explanation on the function of the session argument.

Your code has two parts:

  • user interface (UI): runs the web page, the visual part, on the client side (meaning in the browser of any person using the app, so on their machine)
  • server: runs on the machine where the actual R is installed and the code is executed (so all calculations are done)

Since many users can connect to the same server, the server needs to be able to do different calculations for every person depending on what input they provide. The session variable is a way for Shiny to keep track of who is doing what, and be able to send commands to the right person when needed. This becomes especially important when you are changing the UI, because like I said this normally runs on the client side (and the server can't see that unless the client sends information back to the server, like when he clicks a button etc.)

If the server (= you) wants to change something in the UI of a specific user (even without the user sending some request) the server needs to know which user he needs to send the info to. That's were the session variable comes in. When you use the updateSelectInput on the server, you need to tell it which user's UI it needs to update, because else it might update someone else's or every without them wanting it.

I don't know if I made this clear, but I hope you at least get an idea what it's for. Don't worry, you never need to actually change this variable, but it will be needed in functions where the user interface will change based on your code.

Hope this helps,
PJ

Thanks that makes alot of sense.

So I am starting to get the hang of this I have both my sliders reactive and they are seem to be working but I need to convert my TIme into nanoseconds
the typical equation that I would use is

Pulserfile <- Pulserfile %>% mutate(time_ns = ((Time)*(1.0e9)))

or
DS$time_ns = ((DS$Time)*(1.0e9)
but neither of these seem to work when I put the () after the dataframes
Maybe I am not not putting the equation in the correct place would it be outside of the reactive or render Table or inside?
The plot does will say the time_ns object not found do I need to move the Renderplot lower in the code because R is a line by line program? I apologize if I am not wording this correctly I am self taught and I have only been doing this for about 4 weeks.

Hi,

Can you show me where in your code you like to do this, because that's important to see what Shiny reactivity is in that part.

Thanks

I have changed this so many times. It's not even close to the original but its what I have right now.

  output$myTable1 = renderTable({


    DS()[1:2,] #To call a reactive dataframe, put () behind the name, but treat the rest of the code as usual

    #DS()$Time_ns<- (DS()$Time*(1e9))

    DS_time_ns <- reactive({
     DS_time_ns<- DS["Time"] *1e9
     DS_time_ns
    })


    value <- reactiveVal(0) # rv <- reactiveValues(value = 0)
    observeEvent(input$timeOffset, {
      newTime <- DS()Time - value()  

      
    })
    



})

 # end of server  function