1
votes

I'm building a shiny app that queries an SQL database so the user can ggplot the data. I would like the user to be able to rename factors manually but am struggling to get going. Here is an example of what I want to do:

ui.R

library(markdown)

shinyUI(fluidPage(
  titlePanel("Reactive factor label"),
  sidebarLayout(
    sidebarPanel(

      numericInput("wafer", label = h3("Input wafer ID:"), value = NULL),

      actionButton("do", "Search wafer"),
      textInput("text", label = h3("Factor name to change"), value = ""),
      textInput("text", label = h3("New factor name"), value = ""),
      actionButton("do2", "Change name")

       ),

    mainPanel(
      verbatimTextOutput("waf"), 
      verbatimTextOutput("que"), 
      verbatimTextOutput("pos"),
      dataTableOutput(outputId="tstat")
    )
  )
)
)

server.R

# Create example data

Name <- factor(c("Happy", "New", "Year"))
Id <- 1:3

dd <- data.frame(Id, Name)

con <- dbConnect(RSQLite::SQLite(), ":memory:")
dbWriteTable(con, "dd", dd)
query <-  function(...) dbGetQuery(con, ...)

wq = data.frame()
sq = data.frame()


shinyServer(function(input, output){

  # create data frame to store reactive data set from query
  values <- reactiveValues()
  values$df <- data.frame()

  # Wait for user to search
  d <- eventReactive(input$do, { input$wafer })

  # Reactive SQL query
  a <- reactive({ paste0("Select * from dd where Id=",d()) })
  wq <- reactive({  query( a() ) })

  # Check outputs
  output$waf <- renderPrint(input$wafer)
  output$que <- renderPrint({ a() }) 
  output$pos <- renderPrint( wq()[1,1] )

  # observe d() so that data is not added until user presses action button  
  observe({
    if (!is.null(d())) {
      sq <- reactive({  query( a() ) })

      # add query to reactive data frame
      values$df <- rbind(isolate(values$df), sq())
    }
  })

  output$tstat <- renderDataTable({
    data <- values$df
  })

})

In static R I would normally use data table to rename factors i.e.:

DT <- data.table(df)
DT[Name=="Happy", Name:="Sad"]

But I'm not sure how to go about this with a reactiveValues i.e. values$df.

I have read this (R shiny: How to get an reactive data frame updated each time pressing an actionButton without creating a new reactive data frame?). This lead me to try this but it doesn't do anything (even no error):

observeEvent(input$do2, {
    DT <- data.table(values$df) 
    DT[Name == input$text1, Name := input$text2]
    values$df <- data.frame(values$df)

  })

Perhaps there is a way around this..maybe there is a way to use an action button to "lock in" the data as a new data frame, which can then be used to rename?

Sorry for such a long winded question. My real app is much longer and more complex. I have tried to strip it down.

1
Possibly related: stackoverflow.com/q/20201070/2679518 If your data.frame is itself a reactive object you will not be able to change the names within the data.frame itself.John Paul

1 Answers

1
votes

Your approach works but there are a few issues in your app.

In ui.R, both textInput have the same id, they need to be different so you can refer to them in the server.R. In the observeEvent you posted, you refer to input$text1 and input$text2 so you should change the id of the textInputs to text1 and text2.

In the observeEvent you posted, the last line should be values$df <- as.data.frame(DT), otherwise it does not change anything.