0

I have a shiny app that basically parses a user-uploaded .txt file (see this question I asked regarding the data input and parsing function), and then produces several plots by calling some plotting functions that are located above my shinyServer call in server.R.

The functions called in my server.R script are:

    parseR()      # Returns a dataframe (which is the result of parsing 
                    the user input entered in `fileInput) ([see here][1] for details) 
    senderPosts() # Returns a plot that is shown in tabPanel 1 
    wordFreq()    # Returns a plot that is shown in tabPanel 2
    chatCloud()   # Returns a  plot that is shown in tabPanel 3

I can successfully get the plot in tabPanel 1 to show the levels of a factor in the dataframe returned by parseR(), but I'm not sure how to use this to actually update the plot.

My question is, how can I update a plot based on user input?

Here is server.R:

shinyServer(function(input, output, session) {

  data <- reactive({ 
    req(input$file1)

    inFile <- input$file1 

    df <- parseR(file=inFile$datapath) # Call my parser function 

    updateSelectInput(session, inputId = 'sender', label = 'Sender',
                      choices = levels(df$sender), selected = levels(df$sender))

    return(df)
  })

  # Main page
  output$contents <- renderTable({
    head(data(), 25)
  })

  # tabPanel 1
  output$postCount <-renderPlot({
    senderPosts(file=input$file1$datapath)

  })

  # tabPanel 2
  output$wordCount <-renderPlot({
    wordFreq(file=input$file1$datapath)

    })

  # tabPanel 3
  output$chatCloud <-renderPlot({
    chatCloud(file=input$file1$datapath)

  })

})

ui.R

library(shiny)

suppressMessages(library("wordcloud"))

shinyUI(fluidPage(
  titlePanel("File plotter"),
  tabsetPanel(
    tabPanel("Upload File",
             titlePanel("Upload your file"),
             sidebarLayout(
               sidebarPanel(
                 fileInput('file1', 'Select your file',
                           accept='.txt'
                           ),

                 tags$br()

               ),
               mainPanel(
                 tableOutput('contents'),
                 plotOutput('messageCount')
               )
             )
    ),

    # tabPanel 1 
    tabPanel("Post Count",
             pageWithSidebar(
               headerPanel('Number of posts per user'),
               sidebarPanel(

                 # "Empty inputs" - they will be updated after the data is uploaded
                 selectInput('sender', 'Sender', "")
               ),
               mainPanel(
                 plotOutput('postCount')
               )
             )
    ),

    # tabPanel 2 
    tabPanel("Word Frequency",
             pageWithSidebar(
               headerPanel('Most commonly used words'),
               sidebarPanel(

                 # "Empty inputs" - they will be updated after the data is uploaded
                 selectInput('word', 'Sender', "")
               ),
               mainPanel(
                 plotOutput('wordCount')
               )
             )
    ),

    # tabPanel 3
    tabPanel("Chat Cloud",
             pageWithSidebar(
               headerPanel('Most used words'),
               sidebarPanel(

                 # "Empty inputs" - they will be updated after the data is uploaded
                 selectInput('cloud', 'Sender', "")
               ),
               mainPanel(
                 plotOutput('chatCloud')
               )
             )
    )



  )
)
)
6
  • use the reactive value data() as the data argument passed to your plotting functions inside renderPlot. That will re-plot whenever data() is updated. Commented Nov 16, 2017 at 15:36
  • Render functions are normally reactive. That means whenever an input variable changes value within them. They should automatically be recalculated Commented Nov 16, 2017 at 15:38
  • Also, you don't want to have an update input function within an reactive function you better place that in a separate observe(Event) function. Commented Nov 16, 2017 at 15:42
  • @BertilNestorius - I'm not sure I understand. Would you be able to post a description as an answer (or a link to a description)? Commented Nov 16, 2017 at 15:45
  • @Nate - the data frame that I pass to the plot functions is produced by parseR(). I'm not sure how I can propagate my selections into the parseR() function. Totally confused! Commented Nov 16, 2017 at 15:48

1 Answer 1

1

as I mentioned first you don't want to keep the updateInput in the Reactive function. This is because reactives are lazy evaluation. They are better placed within a observer (observe or observeEvent) which are eager evaluation.

You can then get the value of the User input through input$'inputId'

I would also place the plot calculations in a reactive function but that is not necessary.

shinyServer(function(input, output, session) {

  data <- reactive({ 
    req(input$file1)

    inFile <- input$file1 

    df <- parseR(file=inFile$datapath) # Call my parser function 

    return(df)
  })
  observe({
     df = data()
     updateSelectInput(session, inputId = 'sender', label = 'Sender',
                      choices = levels(df$sender), selected = levels(df$sender))
  })
  # Main page
  output$contents <- renderTable({
    head(data(), 25)
  })

  # tabPanel 1
  output$postCount <-renderPlot({
    senderPosts(file=input$file1$datapath,newParamter = input$sender)

  })

  # tabPanel 2
  output$wordCount <-renderPlot({
    wordFreq(file=input$file1$datapath)

    })

  # tabPanel 3
  output$chatCloud <-renderPlot({
    chatCloud(file=input$file1$datapath)

  })

})
Sign up to request clarification or add additional context in comments.

4 Comments

I have adjusted my shinySever call as you suggest: senderPosts(file=input$file1$datapath, user=input$sender), and my plot function now takes the input$sender : senderPosts <- function(file_in='data/testChat.txt', user=NA){ and passes it to my parseR(): data <- parseR(file=file_in,user=user) ... , which then filters the data frame based on this value, but It's still not working. Is this what you meant?
No, it's not working. When I isolate the two functions they run as expected and produce a plot filtered on user='user', so it must be something happening in the shinySever call. Any ideas?
What do your ui.r look like?
Ah - I've figured it out. Thanks for your help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.