Rachel
Rachel

Reputation: 63

Filter data use textinput in shiny got error: argument is not a character vector

Got Error in enc2utf8: argument is not a character vector. I am using selectInput, checkboxGroupInput, textInput to filter data in the server, and get the above error; I have tried filter(),subset(),which() but they turn to have the same problem when filter the data by over four columns and the arguments are character vectors(eg. corp %in% c('Honda','Nissan'))

In the dataset, there are Market , Corp, Med_type, Med_id, measure, date, value columns.

And in the codes, brands, name_tmp, year are the character vectors used to filter data.

library(shiny)
library(dplyr)
library(DT)

ui<-fluidPage(pageWithSidebar(
  headerPanel('Table'),
  sidebarPanel(
    fileInput('file1', 'Upload Data',
              accept=c('text/csv', 'text/comma-separated-values,text/plain')),
    selectInput('TA',"Market-type",c('Asia','Europe')),
    selectInput('Length',"Length",c('1 year'='0','2 years'='1','3 years'='2','4 years'='3','5 years'='4')),        
    selectInput('NoBrand',"Top Brand/Cor",c('one'='1','two'='2','three'='3','four'='4','five'='5')),
    selectInput('Period',"Period",c('Quarter'='Quarter','YR'='year')),
    checkboxGroupInput('Measure','Measurement',c('Unit','RMB','Dollar')),
    selectInput('Med_type','Med_type',c('Imported','Joint Venture','Local')),
    textInput('Med_id','Med_id',value='Honda;Nissan')),
           
    
  mainPanel(
    dataTableOutput('table')
  )))
  
  
  
  
  server<-function(input,output){
  options(shiny.maxRequestSize=100*1024^2)

  ## importing dataset
  tmp <- reactive({inFile <- input$file1
  if (is.null(inFile))
    return(NULL)
  data<-read_csv(inFile$datapath,na=c("", "NA",'-'))
  
  })
  

  
  
 
 tmp2<-reactive({
   ## modify the inputs
   
   data_df <- tbl_df(tmp())
   year<-(2017-as.numeric(input$Length)):2017
   name_tmp<-as.vector(unlist(strsplit(input$Med_id,';')))
   temp_data<-summarize(group_by(data_df,Corp),VValue=sum(value,na.rm = TRUE))
   brands<-as.vector(arrange(temp_data,desc(VValue))$Corp[1:as.numeric(input$NoBrand)])
   
   ## filtering by the input
   mod_data<-data_df %>% 
     select(Market,Corp,Med_type,Med_id,measure,date,value) %>%
     filter(Market==input$TA,
            Corp%in%brands,
            Med_id%in%name_tmp,
            Med_type==input$Med_type,
            measure==input$Measure,
            substr(date,1,4)%in%year
     )
 
   
   
   
   ## Aggregation() & reformating
   if(input$Period=="year"){
     mod_data$date<-substr(mod_data$date,1,4)
     mod_data<-group_by_if(mod_data,is.character)
     mod_data<-summarise(mod_data,Value=sum(value,na.rm = TRUE))
     
   } else {mod_data<-summarise(group_by_if(mod_data,is.character),Value=sum(value,na.rm=TRUE))}
        
  
   
   
 })
  
  
  ## printing table
  
  output$table<-DT::renderDataTable({tmp2()})
  
  
 
      }
shinyApp(ui=ui,server = server)

Upvotes: 1

Views: 1484

Answers (2)

Rachel
Rachel

Reputation: 63

The problem has been solved. The error actually comes from spread() function. When there is a empty data frame, spread() will call Error in enc2utf8: argument is not a character vector. So I add some conditional arguments to prevent the data frame from being empty once I run the shinyapp. Besides, isolate() is also a useful function for user to take in control of the execution of inputs.

Upvotes: 1

Florian
Florian

Reputation: 25385

Try print(input$measure) before you subset all the data, it is initialized as NULL. You should add:

if(is.null(input$measure))
  measure = unique(data_df$measure)
else
  measure = input$Measure

and modify

measure==input$Measure,

to

measure==measure

So when the use has made no selection, there will be effectively no filter on that column.


Working example

The following works fine for me. Note that I have created my own dataset 'df' and modified your tmp() reactive so it uses my df as input dataset in this example.

df = data.frame(Market=c("Asia","Asia","Europe","Europe"),
                Corp=c("a","b","c","d"),
                Med_type = c('Imported','Joint Venture','Local','Local'),
                Med_id = c("Honda","Honda","Nissan","Nissan"),
                measure=c('Unit','RMB','Dollar','Dollar'),
                date = c('2017','2016','2017','2016'),
                value=c(1,2,3,4 ))


library(shiny)
library(dplyr)
library(DT)

ui<-fluidPage(pageWithSidebar(
  headerPanel('Table'),
  sidebarPanel(
    fileInput('file1', 'Upload Data',
              accept=c('text/csv', 'text/comma-separated-values,text/plain')),
    selectInput('TA',"Market-type",c('Asia','Europe')),
    selectInput('Length',"Length",c('1 year'='0','2 years'='1','3 years'='2','4 years'='3','5 years'='4')),        
    selectInput('NoBrand',"Top Brand/Cor",c('one'='1','two'='2','three'='3','four'='4','five'='5')),
    selectInput('Period',"Period",c('Quarter'='Quarter','YR'='year')),
    checkboxGroupInput('Measure','Measurement',c('Unit','RMB','Dollar')),
    selectInput('Med_type','Med_type',c('Imported','Joint Venture','Local')),
    textInput('Med_id','Med_id',value='Honda;Nissan')),


  mainPanel(
    dataTableOutput('table')
  )))




server<-function(input,output){
  options(shiny.maxRequestSize=100*1024^2)

  ## importing dataset
  tmp <- reactive({ 

  df

  })





  tmp2<-reactive({
    ## modify the inputs

    data_df <- tbl_df(tmp())
    year<-(2017-as.numeric(input$Length)):2017

    name_tmp<-as.vector(unlist(strsplit(input$Med_id,';')))

    temp_data<<-summarize(group_by(data_df,Corp),VValue=sum(value,na.rm = TRUE))

    brands<-as.vector(arrange(temp_data,desc(VValue))$Corp[1:as.numeric(input$NoBrand)])

    if(is.null(input$measure))
      measure = unique(data_df$measure)
    else
      measure = input$Measure

    ## filtering by the input
    mod_data<-data_df %>% 
      select(Market,Corp,Med_type,Med_id,measure,date,value) %>%
      filter(Market==input$TA,
             Corp%in%brands,
             Med_id%in%name_tmp,
             Med_type==input$Med_type,
             measure==measure,
            substr(date,1,4) %in% year
      )


    print(mod_data)

    ## Aggregation() & reformating
    if(input$Period=="year"){
      mod_data$date<-substr(mod_data$date,1,4)
      mod_data<-group_by_if(mod_data,is.character)
      mod_data<-summarise(mod_data,Value=sum(value,na.rm = TRUE))

    } else {mod_data<-summarise(group_by_if(mod_data,is.character),Value=sum(value,na.rm=TRUE))}




  })


  ## printing table

  output$table<-DT::renderDataTable({tmp2()})



}
shinyApp(ui=ui,server = server)

Upvotes: 0

Related Questions