0

Very new to R Shiny! I've looked through a good 20 questions but they don't necessarily address the problem I'm facing.

I have a few dataframes generated from API calls that look something like this:

Project.ID        Author.ID    Author.Name     Fav.Color
Test_Project1      1234             Bob        Green
Test_Project1      2345            Jane         Blue
Test_Project1      2687            Eric         Blue
Test_Project1      8765            Tom           Red           

My goal is to allow users to select a column from the dataframe using a dropdown, select some values to compare from that column using some checkboxes, and add a new column to the same frame reflecting the comparisons that they wanted to make. It should look like this:

Project.ID      Author.ID    Author.Name     Fav.Color    RedvBlue   GreenvRed
Test_Project1    1234            Bob        Green          NA      Green
Test_Project1    2345            Jane         Blue        Blue     NA   
Test_Project1    2687            Eric         Blue        Blue     NA
Test_Project1    8765            Tom           Red         Red     Red

ui.R

ui <- fluidPage(

  sidebarPanel(
     selectInput("viewType", 
                 label = "Select to view:",
                 choices = c(' ', "Projects"), #will have other dataframes to select from 
                 selected = ' '),
     conditionalPanel(
       condition = "input.viewType =='Projects'",
       uiOutput("projectSelection"),
       uiOutput("showMeta"), 
       uiOutput("showVal"),
       textOutput("text")
     )
  ),

  mainPanel(
    DT::dataTableOutput("mytable")
  )
)

server.R

server <- function(input, output) {

    viewSelection <- reactive({
      if(input$viewType == "Projects"){
        projectDT <- getJSON("an API url")

        #replace spaces with dots in headers
        names(projectDT) <- gsub(" ", ".", names(projectDT))

        #show table
        output$mytable <- DT::renderDataTable(DT::datatable(projectDT))


        #Display columns from project to view
        output$showMeta <- renderUI({
          selectInput("metalab",
                      "Metadata Label:",
                      c(" ", unique(as.vector(colnames(projectDT))))
          )
        })

        #Display unique column values to choose from in checkbox
        #Gives Warning: Error in [.data.frame: undefined columns selected
        output$showVal <- renderUI({
          checkboxGroupInput("metaval",
                             "Metadata Value:",
                             choices = unique(as.vector(unlist(projectDT[input$metalab])))
          )
        })

      }

    })

    output$mytable <- DT::renderDataTable({DT::datatable(viewSelection())})  
}

I'm currently struggling to produce a new column in the dataframe based off the user's selections. So far, it displays what I would like it to in terms of the dropdown and checkboxes but I wasn't able to move any further with that. I'm not exactly sure where my problem lies - is my table rendering improperly, am I not adding a new column correctly?

I tried to access input$metalab and input$metaval but they return NULL outside a renderUI/renderText context. I've tried simply duplicating a column based on user choice but this doesn't work either:

projectDT['newCol'] = projectDT[input$metalab]

Any help is greatly appreciated! Sorry for the long blurb!

1 Answer 1

1

Hi is this something in the way of what you want to do?

server <- function(input, output, session) {
  # update datatable
  viewSelection <- reactive({
    if(input$viewType == "Projects"){
      projectDT <- read.table(header = TRUE,
                              text = "Project.ID,Author.ID,Author.Name,Fav.Color
Test_Project1,1234,Bob,Green
Test_Project1,2345,Jane,Blue
Test_Project1,2687,Eric,Blue
                              Test_Project1,8765,Tom,Red",
                              sep = ",")

      #replace spaces with dots in headers
      names(projectDT) <- gsub(" ", ".", names(projectDT))

      projectDT



    }

  })
  #show table
  output$mytable <- DT::renderDataTable(DT::datatable(viewSelection()))
  #Display columns from project to view
  observeEvent({input$addCol},{
    insertUI(
      selector = "#addCol",
      where = "beforeBegin",
      ui = div(
        uiOutput(paste0("showMeta",input$addCol)),
        uiOutput(paste0("showVal",input$addCol))
      )
    )
  })
  lapply(1:5, function(idx){
    output[[paste0("showMeta",idx)]] <- renderUI({
      selectInput(inputId =  paste0("metalab",idx),
                  label =  "Metadata Label:",
                  choices =  c(" ", unique(as.vector(colnames(viewSelection())))),
                  selected = input[[paste0("metalab",idx)]]
      )
    })
  })
  lapply(1:5,
         function(idx){
           output[[paste0("showVal",idx)]] <- renderUI({
             req(input$addCol >= idx)
             checkboxGroupInput(paste0("metaval",idx),
                                "Metadata Value:",
                                choices = unique(as.vector(unlist(viewSelection()[[input[[paste0("metalab",idx)]]]]))),
                                selected = input[[paste0("metaval",idx)]]
             )
             })
         })

  output$showMeta <- renderUI({
  })
    #Display unique column values to choose from in checkbox
    #Gives Warning: Error in [.data.frame: undefined columns selected
  output$showVal <- renderUI({
    checkboxGroupInput("showVal",
                       "Metadata Value:",
                       choices = unique(as.vector(unlist(viewSelection()[[input$metalab]])))
    )
  })

  output$mytable <- DT::renderDataTable({
    req(input$viewType == "Projects")
    projectDT <- viewSelection()
    dta <- NULL
    if(input$addCol > 0){
      dta <- lapply(seq(input$addCol), function(idx){
        if(!is.null(input[[paste0("metalab", idx)]]) &&
           input[[paste0("metalab",idx)]] != " "){
          ifelse(projectDT[[input[[paste0("metalab", idx)]]]] %in% input[[paste0("metaval", idx)]] ,as.character(projectDT[[input[[paste0("metalab", idx)]]]]),NA)
        }
      })
      names(dta) <- sapply(seq(input$addCol),function(idx){
        paste0("Compare",idx,"_",paste0(input[[paste0("metaval",idx)]],collapse = "vs"))
      })
      dta <- as_data_frame( dta[!sapply(dta,is.null)])
    }
    if(!is.null(dta) &&
       !is.null(projectDT) &&
       nrow(dta) == nrow(projectDT)){
      projectDT <- cbind(projectDT,dta)
    }
    DT::datatable(projectDT)})  

}

What I have done is that I have pulled all asignments of outputs out of the reactive statment. This is mainly I to make the code more stable.

Hope this helps!

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

3 Comments

Thank you so much for answering! This is very close to what I would like to do! In your answer, you made it such that the user can add a single new column but how would it be possible to add more than one column? In my illustration above, after the user has created a new column RedvBlue, they're also able to add another column GreenvRed. Sorry if this is a dumb question and thank you for your help!
@carasg Oh das was a bit harder but I think I managed ;-) Any way the User can now add up to 5 new columns
Thank you so much! It does exactly what I want now!

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.