user7919275
user7919275

Reputation:

Creating variables when importing data into the shiny-application, managing the received data

Comrades! Greetings. Please help me out ... there is some significant misunderstanding.

Suppose I created like this data.frame:

df<-data.frame(num = c(1:250),
           app_num =  sample(1:100, 250, replace=T),
           entrance=sample(1:4, 250, replace=T),
           gender=sample(c('m','f'), 250,replace=T),
           age= sample(1:100, 250, replace=T))

I save it in the "*csv" format, using the command:

write.csv2(data_file,file = file.choose(new = T), row.names = FALSE, quote = FALSE)

O.K. Now I want to create a shiny-application for displaying and working with this data like his:

    library("shiny")
    #to work with extra string functions
    library("stringr") 
    library("data.table") 
    library("readr")

    # Define UI for application that draws a histogram
    ui <- fluidPage(
      titlePanel(h2(strong("Analysis of the composition and structure of residents"),
                 align = "center")),
      fileInput(
        inputId="fileInput",
        label="Choose file",
        multiple = FALSE,
        accept = ".csv",
        width = '100%',
        buttonLabel = "Choosing ...",
        placeholder = "No files selected yet"
      ),
      sidebarPanel(
        checkboxGroupInput(inputId="gender", label = "Choosing a gender feature:",
          choices = c("Men" = "m",
                      "Women" = "f"),
          selected= c("Men" = "m",
                      "Women" = "f")),
        sliderInput(inputId = "age", label = "Indicate the age group:",
                    min = 1, max = 100, value = c(1, 100)),
        selectInput(
          inputId = "group",
          label="Indicate the entrance",
          choices=c(1:4),
          selected = c(1:4),
          multiple = TRUE,
          selectize = TRUE,
          width = NULL,
          size = NULL
        )
      ),
      mainPanel(
        navbarPage("",
          tabPanel("Сommon data",
            textOutput(outputId = "text1"),
            ),
          tabPanel("Results table",
                   dataTableOutput(outputId = "content")
            ),
          tabPanel("Graphic data")
        )
      )
    )

    # Define server logic required to draw a histogram
    server <- function(input, output) {

      fileinfor <- reactiveValues(file=NULL,
                                 ext=NULL,
                                 datapath=NULL)
      
      output$content <- renderDataTable({
        fileinfor$file <- input$fileInput
        fileinfor$datapath<-fileinfor$file$datapath
        fileinfor.datapath <- fileinfor$file$datapath
        fileinfor$ext <- tools::file_ext(fileinfor$datapath)
        req(fileinfor$file)
        validate(need(fileinfor$ext== "csv", "Please upload a csv file"))
        fread(fileinfor$datapath,
              showProgress = FALSE,
              sep=";", quote="",header=TRUE)
      })

      output$text1 <- renderUI(renderText({ 
        paste("Check ", fileinfor$datapath)
        }))
      
    }

    # Run the application 
    shinyApp(ui = ui, server = server)

On the server side, I have several questions:

  1. How to get the data correctly so that you can create a variable based on it and use it several times. On the example of my code, you can see that the server-side code block below no longer sees the created variable:

    output $ text1 <- renderUI (renderText ({ paste ("Check", fileinfor $ datapath) }))

  2. Could you show by my example the creation of manipulated variables and their application? Can't figure out where and how to move?

Upvotes: 0

Views: 687

Answers (2)

user7919275
user7919275

Reputation:

First of all, I would like to thank @YBS for this teaching. Thanks to these tips, I managed to solve half of the problem.

The essence of the solution lies in how Shainiy works with variables. In fact, there is no way to store variables like when writing regular code. However, you can write a reactive function that will receive data and issue it to a variable that is within the framework of another function when called.

It should be noted that an explicit mention of this approach was found in the tutorial "Mastering Shiny"

As a result, a version of the working code was obtained. If you want to try the end result, then sequentially sell the following steps:

  1. Create a CSV file for our experiment:

    df<-data.frame(num = c(1:250), app_num = sample(1:100, 250, replace=T), entrance=sample(1:4, 250, replace=T), gender=sample(c('m','f'), 250,replace=T), age= sample(1:100, 250, replace=T))

  2. Save it in the "*csv" format, using the command:

    write.csv2(data_file,file = file.choose(new = T), row.names = FALSE, quote = FALSE)

  3. Use the below mentioned code to create Shiny app:

            library("shiny")
            library("stringr")
            library("data.table")
            library("readr")
            library("DT")
            library("readr")
            library("here")
            library("ggplot2")
            library("dplyr")
            library("tidyr")
    
            # Define UI for application that draws a histogram
            ui <- fluidPage(
              titlePanel(h2(strong("Analysis of the composition and structure of residents"),
                         align = "center")),
              fileInput(
                inputId="fileInput",
                label="Choose file",
                multiple = FALSE,
                accept = ".csv",
                width = '100%',
                buttonLabel = "Choosing ...",
                placeholder = "No files selected yet"
              ),
              sidebarPanel(
                checkboxGroupInput(inputId="gender", label = "Choosing a gender feature:",
                  choices = c("Men" = "M",
                              "Women" = "F"),
                  selected= c("Men" = "M",
                              "Women" = "F")),
                sliderInput(inputId = "age", label = "Indicate the age group:",
                            min = 1, max = 100, value = c(1, 100)),
                selectInput(
                  inputId = "group",
                  label="Indicate the entrance",
                  choices=c(1:4),
                  selected = c(1:4),
                  multiple = TRUE,
                  selectize = TRUE,
                  width = NULL,
                  size = NULL
                )
              ),
              mainPanel(
                navbarPage("",
                  tabPanel("РЎommon data",
                    textOutput(outputId = "text1")
                    ),
                  tabPanel("Results table",
                    dataTableOutput(outputId = "content")
                    ),
                  tabPanel("Graphic data",
                    plotOutput(outputId = "my_plot")
                  )
                )
              )
            )
    
            # Define server logic required to draw a histogram
            server <- function(input, output) {
    
              fileinfor <- reactiveValues(file=NULL,
                                          ext=NULL,
                                          datapath=NULL)
    
    
              gender = reactive({
                gender <- input$gender
                gender
                })
              age = reactive({
                cbind(input$age[1],input$age[2])
                })
              group = reactive({
                input$group
                })
    
              import_data <- reactive({
                req(input$fileInput)
                fileinfor$file <- input$fileInput
                if (is.null(input$fileInput)){ return(NULL) }
                fileinfor$datapath<-fileinfor$file$datapath
                fileinfor$ext <- tools::file_ext(fileinfor$datapath)
                validate(need(fileinfor$ext== "csv", "Please upload a csv file"))
                import_data <- fread(fileinfor$datapath,
                      showProgress = FALSE,
                      sep=";", quote="",header=TRUE)
              })
    
    
              output$content <- renderDT({
                GENDER = gender()
                GROUP = group()
                AGE = age()
                req(import_data())
                data_file <- import_data()
                names(data_file) <- c("ID", "App", "Entrance", "Gender", "Age")
                data_file <- mutate_at(data_file, vars(Gender), as.factor)
                data_file<- mutate(data_file, Gender = factor(Gender, labels = c("F", "M")))
                data_file <- subset(data_file,data_file$Age>=AGE[1]
                                    & data_file$Age<=AGE[2]
                                    & data_file$Entrance %in% GROUP
                                    & data_file$Gender %in% GENDER)
                                         })
    
              output$text1 <- renderText({
                req(input$fileInput)
                gender <- gender()
                paste(length(gender))
              })
    
              output$my_plot= reactivePlot(function(){
                GENDER = gender()
                GROUP = group()
                AGE = age()
                req(import_data())
                data_file <- import_data()
                names(data_file) <- c("ID", "App", "Entrance", "Gender", "Age")
                data_file <- mutate_at(data_file, vars(Gender), as.factor)
                data_file<- mutate(data_file, Gender = factor(Gender, labels = c("F", "M")))
                data_file <- subset(data_file,data_file$Age>=AGE[1]
                                    & data_file$Age<=AGE[2]
                                    & data_file$Entrance %in% GROUP
                                    & data_file$Gender %in% GENDER)
    
                df <- group_by(data_file, data_file$Entrance, data_file$Gender)
                df <- summarise(df, N = n())
                names(df) <- c("Entrance", "Gender", "Quantity")
                df <- mutate_at(df, vars(Gender), as.factor)
                print(data_file$Gender)
                #df <- mutate(df, Gender = factor(Gender, levels  = c("f", "m")))
                df <- complete(df, Gender, fill = list(M = 0, F = 0))
    
                baseR.sbst.rssgn <- function(x) {
                  x[is.na(x)] <- 0
                  x
                }
    
                df$Quantity <- baseR.sbst.rssgn(df$Quantity)
    
                ggplot(data = df, aes(x = factor(df$Gender), y = df$Quantity, fill = df$Gender)) +
                  geom_bar(stat = "identity", position = position_dodge2(0.9)) +
                  geom_text(data = df, aes(label = df$Quantity, y = 0), vjust = -0.5, position = position_dodge2(0.9)) +
                  scale_fill_discrete(name = "Title", labels = c("F", "M")) +
                  facet_wrap(~ df$Entrance, nrow = 1, strip.position = "bottom") +
                  xlab("Distribution of residents by entrances, taking into account gender") +
                  ylab("Number of residents") +
                  theme(
                    strip.placement = "outside",
                    strip.background = element_blank(),
                    axis.text.x = element_blank(),
                    axis.ticks.x = element_blank()
                  )
    
    
                #?(ZMlength ~ Month, data = dat[dat$Lake == LAKE, ],
                #        main = "", xlab = "Month", ylab = "Shell length (mm)")
              })
    
    
            }
    
            # Run the application 
            shinyApp(ui = ui, server = server)
    

What problems did I not solve:

  1. I would like to immediately calculate the maximum and minimum values in the "Age" column when opening a file and change the settings for sliderInput. I would like to do the same with selectInput.
  2. I would like to use the Saini application not only to analyze the downloaded data, but also to replenish the CSV file. In this part, I do not know anything at all.

Upvotes: 0

YBS
YBS

Reputation: 21349

Perhaps you are looking for this.

server <- function(input, output) {
  
  mydf <- reactive({
    req(input$fileInput)
    inData <- input$fileInput
    if (is.null(inData)){ return(NULL) }
    mydata <- read.csv(inData$datapath, header = TRUE, sep=",")
  })
  
  output$content <- renderDT(mydf())
  
  output$text1 <- renderText({
    req(input$fileInput)
    paste("Check ", input$fileInput$datapath)
  })
  
}

Upvotes: 0

Related Questions