简体   繁体   中英

Shiny RStudio app not working due to reactive error

Gives the following error when I run the app:

Error in .getReactiveEnvironment()$currentContext() : Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)

I tried the hands on shiny apps for the first time so I might be missing on some key aspect which I can not figure out. Will appreciate if someone could help.

Here is the code that I have made:

UI:

library(shiny)
shinyUI(pageWithSidebar(
  headerPanel(h1('Sentiment Analyzer for .txt Files'), 
              windowTitle = "Sentiment Analysis"),

  # Getting User Inputs
  sidebarPanel(
    fileInput("fileInput","Please Upload the File"),
    textInput("findPhr5ase", "Enter data to be searched"),
    submitButton('Analyze')
  ),

  mainPanel(
    sidebarPanel(
      verbatimTextOutput("file_Health1")
    ),
    sidebarPanel(
      textOutput("file_Health2")
    ),
    sidebarPanel(
      textOutput("search_Result1")
    ),
    sidebarPanel(
      verbatimTextOutput("search_Result2")
    ),
    sidebarPanel(
      verbatimTextOutput("search_Result3")
    ),
    sidebarPanel(
      wordcloud2Output("sentimentCloud", width = "100%", height = "400px")
    ),
    sidebarPanel(
      plotOutput("sentiment_Analysis", width = "40%", height = "200px")
    ),
    sidebarPanel(
      plotOutput("topSentiments", width = "40%", height = "200px")
    ),
    sidebarPanel(
      dataTableOutput("sentimentScores")
    )
  )
)
)

SERVER:

shinyServer <- function(input, output) {

  observeEvent(input$analysis, {
    #Function to read file
    searchText <- reactive(renderText({input$findPhrase})) 
    #fileType <- renderText({input$selectType})
    read_data_from_file <- function (){
      text <- reactive(readtext({input$fileInput}))
      text <- toString(text[,2])
      text<- gsub("\n", "", text)
      text <- gsub("[\r\n]", "", text)
      return(text)
    }  

    check_data <- function (){
      if (is.null(read_data_from_file()) || is.null(searchText)) {
      return("File or Search Text is empty")
      }
      else {
        return("Starting to analyze file")
      }
    }
    output$file_Health1 <- renderPrint(check_data())

    #WORD COUNT
    output$file_Health2 <- renderText(sapply(read_data_from_file(),stri_stats_latex)['Words',])

    #Function to clean the text file
    clean_data <- function(text){
      #Remove NA values
      NAindices = which(is.na(text))
      if (is.numeric(NAindices) & length(NAindices) > 0) {
        text <- text[-c(NAindices)]
      }
      #Remove single letters and hyphen
      text <- gsub(pattern = "\\b[A-z]\\b{1}", replace = " ", text)
      text <- gsub(pattern = "[-]", replace = " ", text)
      #Conversion to corpus
      docs <- Corpus(VectorSource(text))
      #Cleaning the corpus
      docs <- tm_map(docs, content_transformer(tolower))
      docs <- tm_map(docs, removeNumbers)
      #Remove Stopwords
      docs <- tm_map(docs, removeWords, stopwords("english"))
      docs <- tm_map(docs, removeWords, c("don", "s", "t"))
      docs <- tm_map(docs, removePunctuation)
      docs <- tm_map(docs, stripWhitespace)
      #Rewriting as text file
      writeCorpus(docs, filenames = "clean.txt")
      #Reading cleaned text file
      text1 <- readtext("clean.txt")
      text1 <- toString(text1[,2])
      return(text1)
    }


    #Function to tokenize the words
    tokenize <- function(text){
      words = tokenize_words(text)
      return (words)
    }

    #Hashmap function to get frequency of all words
    get_freq_map <- function(words) {
      hashmap <- hashmap("character")
      for(word in words){
        hashmap[word] <-  0
      }
      for(word in words){
        hashmap[word] <- as.numeric(hashmap[word]) +  1
      }
      return (hashmap)
    }

    #Calling the functions
    text2 = tokenize(clean_data(read_data_from_file()))
    freq_map = get_freq_map(text2[[1]])

    #Function to find frequency of the word given as input
    search_keyword_freq <- function(X) {
      return (freq_map[X])
    }

    #Word count Frequency function
    output$search_Result1 <-renderText(search_keyword_freq(searchText))


    #Reading text file
    text = read_data_from_file()
    #Tokeninzing the sentences
    sentences <- tokenize_sentences(text)

    #Function to create a vector of line numbers where the searched word occurs
    line_nums <- vector()
    for (i in 1:length(sentences[[1]])) {
      filtered_sent_words = tokenize(clean_data(sentences[[1]][i]))
      sentence_freq_map = get_freq_map(filtered_sent_words[[1]])
      freq <- tryCatch(sentence_freq_map[searchText], error = function(e) NULL)
      if (!(is.null(freq))) {
        if (freq > 0) {
          line_nums <- c(line_nums, i)
        }
      }
    }
    #Printing the vector and sentences where the word occurs
    output$search_Result2 <- renderPrint(line_nums)
    output$search_Result3 <- renderPrint(for (i in 1:length(line_nums)) {
                                print(sentences[[1]][line_nums[i]])})

    ##################################################################
    # Word Cloud
    ##################################################################
    # take all the phrases
    df_data <- data.frame(text = sapply(docs, as.character), stringsAsFactors = FALSE)
    # add an id, from 1 to n
    df_data$doc_id <- row.names(df_data)

    #Tokenize
    tidy_docs <- df_data %>% unnest_tokens(word, text)
    par(mar = c(1,1,1,1))
     # split all the words and Word Cloud
    output$sentimentCloud <- renderWordcloud2(tidy_docs %>%inner_join(get_sentiments("bing")) %>%
      count(word, sentiment, sort = TRUE) %>%acast(word ~ sentiment, value.var = "n", fill = 0) %>%
      comparison.cloud(scale=c(4,.3), colors = c("#00B2FF", "red", "#FF0099", "#6600CC"), title.size = 1,
                       title.colors=c("red","blue"),title.bg.colors=c("grey40","grey70"),max.words = 100), 
      env = parent.frame(), quoted = FALSE)

    ####################################################################
    # polarity
    ####################################################################
    #calculate polarity on text column by grouping doc_id
    df_polarity <- polarity(text.var = df_data$text, 
                            grouping.var = df_data$doc_id, 
                            constrain = TRUE,
                            polarity.frame = key.pol,
                            negators = qdapDictionaries::negation.words,
                            amplifiers = qdapDictionaries::amplification.words, 
                            deamplifiers = qdapDictionaries::deamplification.words)
    polarity_score <- scores(df_polarity)
    polarity_res <- as.data.frame((counts(df_polarity)))

    ####################################################################
    # sentiment analysis
    ####################################################################
    df_data2 <- df_data$text
    data_vec <- as.vector(df_data2)
    df_emotion <- get_nrc_sentiment(data_vec)
    df_emotion_sub <- df_emotion[c(1:8)]

    #get the top emotions for each sentence
    df_emotion_sub$top_emotions <- apply(df_emotion_sub[-1], 1, FUN = function(x) 
      paste(names(head(sort(x[x!=0], decreasing = TRUE), 3)), collapse=", "))

    #build the final dataframe containing the results of polarity and sentiment analysis
    pos_vector <- as.character(polarity_res$pos.words)
    neg_vector <- as.character(polarity_res$neg.words)
    neg_words <- polarity_res$neg.words
    #creating the final data frame
    df_final <- data.frame(
      text = df_data$text,
      words = polarity_res$wc,
      positive_words = pos_vector,
      negative_words = neg_vector,
      polarity = polarity_score$ave.polarity,
      emotions = df_emotion_sub$top_emotions
    )

    ################################################

    df_final$Pos_Neg <- ifelse(df_final$polarity > 0,"Positive", 
                               ifelse(df_final$polarity < 0,"Negative","Neutral"))

    output$sentiment_Analysis <- renderPlot(ggplot(df_final, aes(x = factor(1), y = polarity)) +
      geom_boxplot(width = 0.4, fill = "white") +
      geom_jitter(aes(color = Pos_Neg, shape = Pos_Neg), 
                  width = 0.1, size = 1) +
      scale_color_manual(values = c("#00AFBB", "#E7B800", "tomato1")) + 
      labs(x = NULL))   # Remove x axis label

    #counting frequencies of emotions
    f<-data.frame(table(unlist(strsplit(tolower(df_final$emotions), ", "," ,")))) %>% mutate(Freq = sort(Freq))
    #######
    bar <- ggplot(data = f) +
      geom_bar(
        mapping = aes(x = Var1, fill = Freq),
        show.legend = TRUE,
        width = 1
      ) +
      theme(aspect.ratio = 1) +
      labs(x = NULL, y = NULL)

    output$topSentiments <- renderPlot(bar + coord_flip())

    output$sentimentScores <- renderDataTable(df_final[["text","positive_words","negative_words","polarity"]])
  })
}

Thanks for helping me out with this.

HI what you want to do is to replace your functions with the server function with reactive calls. something like this. Instead of:

read_data_from_file <- function (){
      text <- reactive(readtext({input$fileInput}))
      text <- toString(text[,2])
      text<- gsub("\n", "", text)
      text <- gsub("[\r\n]", "", text)
      return(text)
    }  

    check_data <- function (){
      if (is.null(read_data_from_file()) || is.null(searchText)) {
        return("File or Search Text is empty")
      }
      else {
        return("Starting to analyze file")
      }
    }

you should better write:

read_data_from_file <- reactve({
      text <- reactive(readtext({input$fileInput}))
      text <- toString(text[,2])
      text<- gsub("\n", "", text)
      text <- gsub("[\r\n]", "", text)
      return(text)
    })  

    check_data <- reactive({
      if (is.null(read_data_from_file()) || is.null(searchText() )) {
        return("File or Search Text is empty")
      }
      else {
        return("Starting to analyze file")
      }
    })

please also not that I added () after searchText this is the way to reference reactive objects. They are like functions without any parameters.

Hope this helps!!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM