0

Problem:

I was trying to build a shiny app that plot frequency of n-grams based on a user specified column from a user uploaded csv. In addition, a function was added to plot the senetiment over time, based on a date column specified by the user as well.

The app was working okay locally, with Warning, but failed work after published. Please see the following for a reproducible example.

Preparation: libraries and example data

# Load R packages
library(shiny)
library(tidyverse)
library(shinythemes)
library(lubridate)
library(tidytext)
library(textdata)

# Creating a example csv file for upload
Sample_csv <- 
  data.frame(text = janeaustenr::emma,
             id = 1:length(janeaustenr::emma),
             date = sample(seq(as.Date('1900/01/01'), as.Date('1920/01/01'), by="day"),
                           replace = T,
                           length(janeaustenr::emma)))
write.csv(Sample_csv, "Sample_csv.csv", row.names = F)

UI

ui <- fluidPage(theme = shinytheme("united"),
                titlePanel("Text glancer"),
                sidebarLayout(
                  sidebarPanel(
                    # Input: Select a file ----
                    fileInput("csv_file", "Feed csv here",
                              multiple = FALSE,
                              accept = c(".csv")),
                        #Conditional panel 
                    conditionalPanel(
                      # use a server side condition
                      condition = "output$fileUploaded",
                      # Input: Select  ----
                      uiOutput("text_select"),
                      # Input: Select  ----
                      uiOutput("date_select"),
                      # Input: Simple integer interval ----
                      sliderInput("top_frequency", "Top n ngrams to be plotted:",
                                  min = 5, max = 20, value = 10),
                      # Input: Select  ----
                      selectInput("ngrams", "Ngrams of your choice:",
                                  c("Single word" = 1,
                                    "Bigram" = 2,
                                    "Trigram" = 3)
                      )
                    ),
                    # Submit bottom
                    submitButton("Update View", icon("refresh"))
                  ), 
                  # sidebarPanel
                  mainPanel(
                    tabsetPanel(
                      tabPanel(h2("Most frequenlty used n-grams"),
                               plotOutput("frequency_plot", height = 900, width = 1200)),
                      tabPanel(h2("Sentiment of the months"),
                               plotOutput("sentiment_plot", height = 900, width = 1200))
                    )
                  )
                ) 
)

server

server <- function(input, output, session) {
  
  # create reactive version of the dataset (a data.frame object)
  LOAD_DATA <- reactive({
    infile <- input$csv_file
    if (is.null(infile)) 
    {return(NULL)}
    {read_csv(infile$datapath)}
  })
  
  
  # inform conditionalPanel wheter dropdowns sohould be hidden
  output$fileUploaded <- reactive({
    return(!is.null(LOAD_DATA()))
  })
  outputOptions(output, 'fileUploaded', suspendWhenHidden=FALSE)
  
  ## update 'column' selectors
  output$text_select <- renderUI({
    if(is.null(LOAD_DATA()))
    {return(NULL)}
    else
      selectInput("text_col", "Select the text column:", colnames(LOAD_DATA()))
  })
  
  output$date_select <- renderUI({
    if(is.null(LOAD_DATA()))
    {return(NULL)}
    else
      selectInput("date_col", "Select the date column (ymd):", colnames(LOAD_DATA())) 
  })
  
  # Create reactive parameters
  TOP_FREQUENCY <- reactive({
    input$top_frequency
  })
  N_GRAMS <- reactive({
    as.numeric(as.character(input$ngrams))
  })

  # Output frequency of ngrams
  output$frequency_plot <- renderPlot( {
    
    if(is.null(LOAD_DATA()))
    {return(NULL)}
    
    else{
      
      WORK_DATA <-  LOAD_DATA()[,c(input$text_col,
                                   input$date_col)]
      names(WORK_DATA) <- c("TEXTS", "DATES")
      
      CSV_DOC_N_Grams <-
        WORK_DATA %>%
        # LOAD_DATA() %>%
        # select(TEXTS = TEXT_COL(), DATES = DATE_COL()) %>%
        mutate(TEXTS = gsub("http.*", " ", TEXTS)) %>%
        # mutate(text = gsub("\\@.* |\\@.* .|\\@.* ,", " ", text)) %>%
        unnest_tokens(words, TEXTS, token = "ngrams", n = N_GRAMS()) %>%
        select(words) %>%
        filter(str_detect(words, "[a-zA-Z]")) %>%
        separate(words,  c("word1","word2","word3"),sep = " ", remove = F) %>%
        filter(! word1 %in% stop_words$word &
                 ! word2 %in% stop_words$word&
                 ! word3 %in% stop_words$word)
      
      #Counting ngrams
      CSV_DOC_N_Gramss_Count <-
        CSV_DOC_N_Grams %>%
        count(words, sort=T) %>%
        select(N_Gram_Text = words,
               N_Gram_Count = n)
      
      #Plotting ngram frequency
      CSV_DOC_N_Gramss_Count_freq <-
        CSV_DOC_N_Gramss_Count %>%
        mutate(N_Gram_Text = fct_reorder(N_Gram_Text, N_Gram_Count)) %>%
        top_n(TOP_FREQUENCY(), N_Gram_Count) %>%                          
        ggplot(aes(x = N_Gram_Text,
                   y = N_Gram_Count,
                   fill = N_Gram_Count)) +
        geom_col()+
        coord_flip() +
        scale_fill_gradient2()+
        labs(title = paste0("Top ", TOP_FREQUENCY(), " ngrams used in csv doc"),
             x = "ngrams",
             y = "frequency") +
        theme_bw()+
        theme(legend.position = "none",
              axis.text.x = element_text(face='bold',size=12),
              axis.text.y = element_text(face='bold',size=12),
              axis.title.x = element_text(face='bold',size=18),
              axis.title.y = element_blank())
      print(CSV_DOC_N_Gramss_Count_freq)
    }
  })
  
  
  output$sentiment_plot <- renderPlot( {
    
    if(is.null(LOAD_DATA())){return(NULL)}
    
    else{
      
      WORK_DATA <-  LOAD_DATA()[,c(input$text_col,
                                   input$date_col)]
      names(WORK_DATA) <- c("TEXTS", "DATES")
      
      tk_afinn <-
        WORK_DATA %>%
        mutate(TEXTS = gsub("http.*", " ", TEXTS)) %>%
        unnest_tokens(word, TEXTS) %>%
        filter(! word %in% stop_words$word) %>%
        filter(str_detect(word, "[a-zA-Z]")) %>%
        filter(! DATES %in% NA) %>%
        inner_join(get_sentiments("afinn")) %>%
        mutate(YEAR_Month = ymd(paste(year(DATES),
                                      month(DATES),
                                      "1", sep="-"))) %>%
        group_by(index = YEAR_Month) %>%
        summarise(sentiment = sum(value))
      
      tk_afinn_plot <-
        tk_afinn  %>%
        ggplot(aes(x = index, y = sentiment)) +
        geom_line()+
        labs(x = "date (year-month)",
             y = "sentiment of the month") +
        theme_bw()+
        theme(legend.position = "none",
              axis.text.x = element_text(face='bold',size=12),
              axis.text.y = element_text(face='bold',size=12),
              axis.title.x = element_text(face='bold',size=18),
              axis.title.y = element_blank())
      print(tk_afinn_plot)
    }
  })
} 

Fuse

shinyApp(ui = ui, server = server)

Warnings:

After loading the csv file, the local app reports : "Problem with mutate() input TEXTS. object 'TEXTS' not found Input TEXTS is gsub("http.*", " ", TEXTS)."

After specify the text column and date column, both tab showed plots. However, after publishing it to shinyapp.io, it reports error and would not run.

Can anybody help with this issue? I have consulted the other thread includin this>https://stackoverflow.com/questions/47248534/dynamically-list-choices-for-selectinput-from-a-user-selected-column, but still no luck.

Any insight would be greatly appreciated!

0 Answers0