Bahae Omid
Bahae Omid

Reputation: 574

Shiny reactive function is not updating as expected

Original question posted here: Shiny reactive Unexpected Behavior
The question is being re-posted here in an attempt to improve the original question posted previously in the link provided above as I was not able to receive any assistance.

Objective: In brief, the purpose of this app is to allow the user to perform search, filter, and slice and dice the data, provided in from of a dataframe, based on various inputs provided to the user.

As part of the server function, a reactive function named index has been defined to look up the indices corresponding to the user's inputs. The reactive function,index, uses grep and which functions to locate the respective indices in the dataframe df.

I have included a reproducible code and tried to include comments, where appropriate.

Further explanation about the code:
The title of this question is just my own speculation and it's based on the assumption that the code within index is correct. there might be a fundamental issue with the code within index and not the reactivity of the index function necessarily. In order to test this, as part of the server function, I have included a function printIndex in order to print the results of index to make sure that it works properly.

I have personally tried printing the results of ind.j, ind.c, ind.l,ind.d, ind.s, and ind.all each one individually to the console and they seemed to all produce the right results. However, when I test the results of ind it's not quite what I expect so I'm wondering if it's the reactivity or the line of code that's problematic. What the ind intends to do is to take the list of all the looked-up indices, stored in ind.all, and applies the intersect function recursively to find the common elements from all the sublists in ind.all.

As I mentioned above, the index function works fine for individual filters. However, when I enter values for all the indices, as a user, the function does not update to the correct list of indices as expected. For example, you can try inputting "application" in the Job textInput, "Gas Drive Global" in the Company selectizeInput, and "Calgary" in the Location textInput at the same time and hit Search!. You will see that the data table does not return any results while this clearly corresponds to the 1st row of the dataframe df.

#Load required packages
ListofPackages= c('shiny','ggplot2','scales')
lapply(ListofPackages,require,character.only=TRUE)

#Define the dataframe on which the search will be performed
df <- data.frame(Job=c('Applications Engineer ââ¬â Gas Drive',
                       'Engineer, Operations',
                       'Project Engineer',
                       'Project Engineer (Oil & Gas)',
                       'Project Engineer',
                       'Junior Engineer',
                       'Engineer, Operations',
                       'Research and Development (R&D) Junior Engineer',
                       'JUNIOR QUALITY ENGINEER',
                       'Junior Systems Design and Support Engineer',
                       'Mechanical Engineer Calgary, AB',
                       'Applications Engineer',
                       'Project Engineer',
                       'Pipeline Engineer',
                       'Development Engineer',
                       'Specialist Engineering Finance',
                       'Mechanical Engineer - Sudbury',
                       'Project Cost Analyst (12 month term)',
                       'Project Controls Functional Analyst',
                       'Project Controls Professionals'),
             Company=c('Gas Drive Global',
                       'Agrium Wholesale',
                       'City of Calgary',
                       'Stantec',
                       'Shell',
                       'Canadian National Railway',
                       'Pembina Pipeline Corporation',
                       'Velan Inc.',
                       'G.W. Goudreau Personnel Services Ltd',
                       'Stratified Automotive Controls',
                       'Pason Systems Corp.',
                       'Howden',
                       'Plains Midstream Canada',
                       'Amec Foster Wheeler',
                       'Red Bend Software',
                       'Canadian Pacific',
                       'GENIVAR',
                       'Thales',
                       'AltaGas Ltd.','BEMAC Construction Corp.'),
            Location=c('Calgary',
                      'Redwater',
                      'Calgary',
                      'Edmonton',
                      'Sarnia',
                      'Montréal',
                      'Calgary',
                      'Montréal',
                      'Windsor',
                      'Vancouver',
                      'Calgary',
                      'Winnipeg',
                      'Calgary',
                      'Calgary',
                      'Engineer',
                      'Calgary',
                      'Greater Sudbury',
                      'Ottawa',
                      'Calgary',
                      'Calgary'),
              Posted=c(1,
                       1,
                       1,
                       2,
                       2,
                       1,
                       4,
                       5,
                       6,
                       4,
                       1,
                       5,
                       5,
                       3,
                       1,
                       1,
                       15,
                       1,
                       1,
                       13),
             Source=c('Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed',
                      'Indeed'),
                url=c('http://ca.indeed.com/rc/clk?jk=2371e16aab902f84',
                      'http://ca.indeed.com/rc/clk?jk=428facb738edd397',
                      'http://ca.indeed.com/rc/clk?jk=e15d8fe4d362279b',
                      'http://ca.indeed.com/rc/clk?jk=28c1464fd4e28b24',
                      'http://ca.indeed.com/rc/clk?jk=736ec57bf6902b93',
                      'http://ca.indeed.com/rc/clk?jk=bdc9999eae922645',
                      'http://ca.indeed.com/rc/clk?jk=3a4588fca0e600b1',
                      'http://ca.indeed.com/rc/clk?jk=71f1abcd100850c6',
                      'http://ca.indeed.com/cmp/G.W.Goudreau-Personnel-Services-Ltd/jobs/Junior-Quality-Engineer-3237601a1f3d3abc?r=1',
                      'http://ca.indeed.com/cmp/Stratified-Automotive-Controls/jobs/Junior-System-Design-Support-Engineer-1d916a435e69b8ce?r=1',
                      'http://ca.indeed.com/rc/clk?jk=fca9a784a37ece8a',
                      'http://ca.indeed.com/rc/clk?jk=b2d0975c638c03a8',
                      'http://ca.indeed.com/rc/clk?jk=c92725272c5f9ced',
                      'http://ca.indeed.com/rc/clk?jk=cd97c050df64787c',
                      'http://ca.indeed.com/rc/clk?jk=e6e278ed52532f73',
                      'http://ca.indeed.com/rc/clk?jk=a1f14d52c7798d7b',
                      'http://ca.indeed.com/rc/clk?jk=112350d5e020241f',
                      'http://ca.indeed.com/rc/clk?jk=a324c2dcade7dc5c',
                      'http://ca.indeed.com/rc/clk?jk=77895efdf28ad6fa',
                      'http://ca.indeed.com/cmp/BEMAC-Construction-Corp./jobs/Project-Control-Professional-90796e764f064a51?r=1'))

server <- function(input,output,session){

    #Server-side search for the choices argument of selectizeInput in ui.R
    updateSelectizeInput(session, 'c', choices = as.character(df$Company), server = TRUE)

    #Create a reactive function to look up the indices correponding to the user's inputs
    index <- reactive({
        ind.j <- if(input$j=='') NULL else grep(input$j,df[,'Job'],ignore.case = T)
        ind.c <- {tmp<-lapply(input$c, function(x) {which(df[,'Company']==x)}); Reduce(union,tmp)}
        ind.l <- if(input$l=='') NULL else grep(input$l,df[,'Location'],ignore.case = T)
        ind.d <- which(df[,'Posted']<=input$d)
        ind.s <- {tmp<-lapply(input$s, function(x) {which(df[,'Source']==x)}); Reduce(union,tmp)}
        ind.all <- list(ind.j,ind.c,ind.l,ind.d,ind.s)
        ind <- if(is.null(ind.s)) NULL else {ind.null<- which(lapply(ind.all,is.null)==TRUE) ;Reduce(intersect,ind.all[-ind.null])}

    })

    #Create a reactive function to return the search results by returning the indices looked up in the index function above
    search <- reactive({

              df[index(),]

    })

    #Print the results of the index function above to test if it works properly
    output$printIndex <- renderUI({
           list(index())
    })

    #Send the searchresult table to ui.R to print the results of the search function above
    output$searchresult <- renderDataTable({
        input$action6   #triggered only when button is pressed
        if(input$action6==0) return() 
        else{isolate({
            transformed <- transform(search(), Link = paste('<a href = ', shQuote(url), '>', 'Click</a>'))
            transformed <- transformed[,c(1:3,5,7,4,6)] #Rearrange columns
            transformed[-7] #Remove last column
        })
        }
    }, option=list(autoWidth=FALSE,pageLength=100,
                   columnDefs = list(list(targets =c(5,6) -1, searchable = FALSE),list(sWidth=c("100px")))))


}

ui <- shinyUI(fluidPage(

    #Display datatable filters on top
    tags$head(tags$style("tfoot {display: table-header-group;}")),        

    #Add a title
    h1('Power Search'),

    #Use the Sidebar layout
    sidebarLayout(
        sidebarPanel(

            #Add various fields for the user in order to search the dataframe  
                     h5('Note: Running the app takes a little while at startup.'),
                     helpText('Job:'),
                     textInput('j',''),
                     helpText('Company:'),
                     selectizeInput('c','',choices=NULL,multiple=T),
                     helpText('Location:'),
                     textInput('l',''),
                     sliderInput('d','Posted (days ago)',min = 0,max = 60,step = 5,value = 60),
                     checkboxGroupInput('s','',choices = c('Indeed','Glassdoor'),selected = c('Indeed','Glassdoor')),
                     actionButton('action6','Search!')
        ),


        mainPanel(

            #Display results
            htmlOutput('printIndex'),
            dataTableOutput('searchresult')
        )      

    )
))

shinyApp(ui = ui, server = server)

Upvotes: 3

Views: 1653

Answers (1)

jdharrison
jdharrison

Reputation: 30425

The problem you have is with the which function:

> which(rep(FALSE, 5))
integer(0)

You can change:

ind <- if(is.null(ind.s)){
  NULL
}else{
  ind.null<- which(lapply(ind.all,is.null)==TRUE)
  Reduce(intersect,ind.all[-ind.null])
}

to

ind <- if(is.null(ind.s)){
  NULL
}else{
  Reduce(intersect,ind.all[!sapply(ind.all,is.null)])
}

enter image description here

Upvotes: 4

Related Questions