NumericInput takes a random sample - is this even possible?

I'm trying to build an app so the user can upload data in the UI, then draw a random sample from it based on a characteristic of the data, then download the sample they made.

Once the data table is uploaded, is it possible for a numeric input to take a sample of it?

So if I upload the location of all of the grocery stores in Nebraska, and want a random sample of 10 from zipcode 68503, would I start by filtering for 68503 then have my (theoretical) sample input then a "generate" button?

The people I'm working with were doing this all back-end in SAS using surveyselect.

I think this project was out of my league....any ideas would be appreciated, informative links are super double appreciated.

This is the only code I have so far. Again, ANY help is appreciated :grinning:

library(shiny)
library(DT)

Define UI for data upload app ----

ui <- fluidPage(

# App title ----
titlePanel("Project Extra Mile List Generator"),

# Sidebar layout with input and output definitions ----
sidebarLayout(
    
    # Sidebar panel for inputs ----
    sidebarPanel(
     
        # Input: Select a file ----
        fileInput("file1", "Choose CSV File",
                  multiple = FALSE,
                  accept = c("text/csv",
                             "text/comma-separated-values,text/plain",
                             ".csv")),
        # Button
        actionButton("update", "Generate", 
                     class = "btn-primary",style='padding:4px; font-size:120%')
        
    ),
    
    # Main panel for displaying outputs ----
    mainPanel(
        
        # Output: Data file ----
        DTOutput("contents")
        
    )
)

)

Define server logic to read selected file ----

server <- function(input, output) {

#Table
output$contents <- renderDT({
    
    req(input$file1)
    
    df <- read.csv(input$file1$datapath)    
    
})

}

Create Shiny app ----

shinyApp(ui, server)

1 Like

Hi,

Although the question seems easy it required quite some Shiny tricks to get the desired result.
Here is the app I made (read comments how to generate sample data)

library(shiny)
library(DT)

ui <- fluidPage(
    sidebarLayout(
        
        # Sidebar panel for inputs ----
        sidebarPanel(
            
            # Input: Select a file ----
            fileInput("file1", "Choose CSV File",
                      multiple = FALSE,
                      accept = c("text/csv",
                                 "text/comma-separated-values,text/plain",
                                 ".csv")),
            
            selectInput("variable", "Choose variable", choices = ""),
            selectInput("subset", "Choose subset", choices = ""),
            numericInput("nSamples", "How many random samples?", value = 1),
            
            # Button
            actionButton("update", "Generate", 
                         class = "btn-primary",style='padding:4px; font-size:120%'),
            
            downloadLink("downloadData", "Download")
            
        ),
        
        # Main panel for displaying outputs ----
        mainPanel(
            
            # Output: Data file ----
            DTOutput("contents")
            
        )
    )
)

server <- function(input, output, session) {
    
    #Uncomment, Run and delete these two commented lines of code to get sample file to test...
    # df = data.frame(ID = 1:10, zip = c(rep(68503, 5), rep(45763, 5)))
    # write.csv(df, "testData.csv", row.names = F)
    
    df = reactiveVal()
    randomSubset = reactiveVal()
    
    #Change the variables based on the columns in the file
    observeEvent(input$file1, {
        df(read.csv(input$file1$datapath))
        updateSelectInput(session, "variable", choices = colnames(df()))
    })
    
    #For the selected variable, display all different options
    observeEvent(input$variable, {
        updateSelectInput(session, "subset", choices = unique(df()[,input$variable]))
    })
    
    #On update, pick n samples from the selected sub category
    observeEvent(input$update, {
        randomSubset(df()[eval(parse(text = paste("df()$",input$variable, "==", input$subset, sep = ""))),])
        randomSubset(randomSubset()[sample(1:nrow(randomSubset()), input$nSamples), ])
        output$contents <- renderDT({
            randomSubset()
        })
    })
    
    #Download csv when completed
    output$downloadData <- downloadHandler(
        filename = function() {
            paste("randomSample.csv", sep="")
        },
        content = function(file) {
            write.csv(randomSubset(), file, row.names = F)
        }
    )

}

shinyApp(ui, server)

It should work, but beware I did NOT implement any error handling, meaning that if a user uploads a wrong file or tries to pick too many random samples from a dataset that doesn't have them, the app will crash.

Lemme know what you think...

PJ

1 Like

Hi PJ,

THANK YOU SO MUCH. This is everything, this is exactly what I needed!! I can't believe it!! I've been stuck on this for MONTHS. Is there anything I can do to give you credit when I turn this in? I'm so incredibly appreciative of your help.

Erin

Hi Erin,

I'm happy it solved your problem! Honestly, your genuine praise is more than enough credit :slight_smile: Just label my answer as the solution and I'm good.

In case you need some extra help, feel free to send me a message here.

Grtz,
PJ

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.