I am building a shiny app. The directory name is "nextword-app"The app is supposed to read in a four word phrase, look it up to see if it is in a dictionary, and return the most likely word that follows the phrase. I've already written a function called whatsnexta that predicts the fifth word after a four word phrase is typed in. This function I put in the helpers.R file which is in the "nextword-app" directory. The dictionary "dictionary.rds" is in a data folder in the directory. I think all the files are in the right place and the problem is in the app.R, most likely in the server function. Here is my app.R
# Load packages ----
library(dplyr)
library(stringr)
# Load data ----
source("nextword-app/helpers.R")
dat <- readRDS("nextword-app/data/dictionary.rds")
library(shiny)
ui <- fluidPage(headerPanel("What Will They Say Next?"),
textInput(inputId="predictor_words", label = "type in four words"),
textOutput(outputId="predicted_word")
)
server <- function(input, output){
output$predicted_word <- renderText({
data <-dictionary.rds
whatsnexta(phrase=input$predictor_words)})
}
shinyApp (ui=ui, server=server)
The error message I get is here:
Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
Warning in file(filename, "r", encoding = encoding) :
cannot open file 'nextword-app/helpers.R': No such file or directory
Error in file(filename, "r", encoding = encoding) :
cannot open the connection
library(dplyr)
library(stringr)
# Load data ----
source("helpers.R")
dat <- readRDS("data/dictionary.rds")
library(shiny)
ui <- fluidPage(headerPanel("What Will They Say Next?"),
textInput(inputId="predictor_words", label = "type in four words"),
textOutput(outputId="predicted_word")
)
server <- function(input, output){
output$predicted_word <- renderText({
data <-dictionary.rds
whatsnexta(phrase=input$predictor_words)})
}
shinyApp (ui=ui, server=server)
A new error message says:
Loading required package: shiny
Warning: package ‘shiny’ was built under R version 3.6.1
Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
Warning in gzfile(file, "rb") :
cannot open compressed file 'dictionary.rds', probable reason 'No such file or directory'
Error in gzfile(file, "rb") : cannot open the connection
Just to be sure, what is the output of runing list.files(path = "path_to_nextword-app",recursive = TRUE)? (but using the actual path to your "nextword-app" folder)
after a few seconds, I get a very long list of all the files in the path.
[293] "nextword-app/app.R"
[294] "nextword-app/data/dictionary.rds"
[295] "nextword-app/helpers.R"
...
are on the list of the many entries.
[1000] "R/win-library/3.4/BH/include/boost/asio/detail/std_thread.hpp"
[ reached getOption("max.print") -- omitted 59333 entries ]
First, I commented out a load data statement in my helpers.R file. The helpers.R file now looks like this
#dat<- readRDS("dictionary.rds")
#function that outputs the next word after a phrase is typed in
library(stringr)
library(dplyr)
nxtword1<- function(word){dat %>% filter(word1 == word) %>% select(-word1)}
##function to change ngram to n-1 gram
less1gram <- function(x){str_replace(x, "^[^ ]+ ", "")
}
# To print out the most common unigrams instead of a row of NAs,
##should no match be found
whatsnexta <- function(phrase) {
nwords <-str_count(phrase, pattern=" ")
while (!(phrase %in% dat$word1) && nwords >=1){
phrase<- less1gram(phrase)
nwords<-str_count(phrase, pattern=" ")
#if (!(phrase %in% dat$word1) && nwords>0)
#{ print(nxtword1(phrase)[1:5, 1])}
if ((phrase %in% dat$word1) ){
print(nxtword1(phrase)[1:5, 1])
}
if (!(phrase %in% dat$word1) && nwords==0)
{ print(c("the","to", "and", "in", "of"))}
}
}
Next, I reran the app. It seemed to go further than previously, even showed an app, that had an error message on it. The message on the console
> runApp('nextword-app')
Listening on http://127.0.0.1:7644
Warning: Error in renderText: object 'dictionary.rds' not found
96: renderText [C:\Users\mlrob\OneDrive\Documents\nextword-app/app.R#21]
95: func
82: origRenderFunc
81: output$predicted_word
1: runApp
# Load packages ----
library(dplyr)
library(stringr)
# Load packages ----
library(dplyr)
library(stringr)
# Load data ----
source("helpers.R")
dat <- readRDS("data/dictionary.rds")
library(stringr)
library(dplyr)
library(shiny)
ui <- fluidPage(headerPanel("What Will They Say Next?"),
textInput(inputId="predictor_words", label = "type in four words"),
textOutput(outputId="predicted_word")
)
server <- function(input, output){
output$predicted_word <- renderText({
#dat <-dictionary.rds
phrase <- textInput$predictor_words
whatsnexta(phrase=input$predictor_words)})
}
shinyApp (ui=ui, server=server)
The app will be there, but there is another error message:
> shiny::runApp('nextword-app')
runApp('nextword-app')
Listening on http://127.0.0.1:4886
Warning: Error in $: object of type 'closure' is not subsettable
96: renderText [C:\Users\mlrob\OneDrive\Documents\nextword-app/app.R#25]
95: func
82: origRenderFunc
81: output$predicted_word
1: runApp
I re-ran the function whatsnexta, which is in my helpers.R file. It was working.
Whenever you see "object of type 'closure' is not subsettable", it's a good idea to first check for a syntax error or typo somewhere. A "closure" is R's word for a function, so R is saying that you tried to subset a function using $ (which you almost certainly did not intend to do!).
In this case, the error message is also telling us that the problem is in the renderText() function that's being supplied as the definition for output$predicted_word. What jumps out to me in that block of code is:
phrase <- textInput$predictor_words
I think you meant to type input$predictor_words there?
You also don't seem to be actually using the phrase variable that you defined in that line. Two ways of fixing that:
# Load packages ----
library(dplyr)
library(stringr)
# Load data ----
source("helpers.R")
dat <- readRDS("data/dictionary.rds")
library(stringr)
library(dplyr)
library(shiny)
ui <- fluidPage(headerPanel("What Will They Say Next?"),
textInput(inputId="predictor_words", label = "type in four words"),
textOutput(outputId="predicted_word")
)
server <- function(input, output){
output$predicted_word <- renderText({
whatsnexta(phrase = input$predictor_words)
paste("the next word is", output$predicted_word)
})
}
shinyApp (ui=ui, server=server)
My output was showing in the console window. I've been trying to get the output to show in the Shiny window, in the main panel. I will get this error message
Listening on http://127.0.0.1:4842
Warning: Error in $.shinyoutput: Reading objects from shinyoutput object not allowed.
100: stop
99: $.shinyoutput
96: renderText [C:\Users\mlrob\OneDrive\Documents\nextword-app/app.R#22]
95: func
82: origRenderFunc
81: output$predicted_word
1: runApp
Yes, check your function and make sure that it works as intended, I can't give you any specific advice about this since I can't test your function (you have not provided a REPRoducible EXample (reprex) or sample data).
#Created a dictionary of unigrams, bigrams, trigrams.
dat<- data.frame(word1=c( "will", "like","get", "look", "next", "social",
"cinco_de","manufacturer_custom", "custom_built"), word2=c(" ", " ", " ",
"like","week", "media", "mayo", "built", "painted"), frequency = c( 5153, 5081, 4821,
559, 478,465, 172,171,171 ) )
dat
#Here is a function to look up words in the dictionary (named dat)
# write a function that returns the second word when the prefix is typed in.
library(dplyr)
library(stringr)
whatsnext5 <- function(phrase) {
nwords <-str_count(phrase, pattern=" ")
##The number of words in the prefix is nwords +1
##If there is no match in the dat the next smaller ngram will be looked up. This continues until a
##match is found. Then the matching words will be outputted.
while (!(phrase %in% dat$word1) && nwords >=1){
#phrase<- less1gram(phrase)
phrase <-str_replace(phrase, "^[^ ]+ ", "")
nwords<-str_count(phrase, pattern=" ")
##Match found
if ((phrase %in% dat$word1) ){
answer <-dat %>% filter(word1 == phrase) %>% select(-word1)
print(answer[1:5, 1])
}
##Match not found
if (!(phrase %in% dat$word1) && nwords==0)
#Here no match was found, so the five most common unigrams are outputted.
{ print(c("the","to", "and", "in", "of"))}
}
}
whatsnext5("manufacturer_custom")
Nothing happened here--no error message, just nothing.
This seems like an assignment to me so I'm not going to fix your function for you, but I can give you a hint, the logical condition in the while() statement returns FALSE, so the code inside the loop never gets executed.
> whatsnext("It was a custom built")
[1] <NA> <NA> <NA> <NA> <NA>
Levels: built like mayo media painted week
[1] <NA> <NA> <NA> <NA> <NA>
Levels: built like mayo media painted week
[1] painted <NA> <NA> <NA> <NA>
Levels: built like mayo media painted week
>
Why did R print out three times? What do Levels: indicate?
How can I get answer[1:5, 1] ? I wanted it to show up in the Shiny window as text..
Because you are using a while loop and it is going to print an answer for each iteration, this is how you have designed your code, if this is not what you want, check your logic again.
The word2 column (the one you are subseting with answer[1:5, 1]) is a factor variable and levels are the unique values in that variable.
Sorry but answering that would be the same as doing your work for you and that would go against our homework policy
I fixed my helpers.R and I got answer[1:5, 1] Here is my code
#function that outputs the next word after a phrase is typed in
library(stringr)
library(dplyr)
#nxtword1<- function(word){dat %>% filter(word1 == word) %>% select(-word1)}
##function to change ngram to n-1 gram
#less1gram <- function(x){str_replace(x, "^[^ ]+ ", "")
#}
# To print out the most common unigrams instead of a row of NAs,
##should no match be found. The number of words in the prefix is nwords + 1
whatsnexta <- function(phrase) {
nwords <-str_count(phrase, pattern=" ")
##While loop works when no matches are found in tge dictionary and there is more than one word in
#the prefix
while (!(phrase %in% dat$word1) && nwords >=1){
#phrase<- less1gram(phrase)
phrase <-str_replace(phrase, "^[^ ]+ ", "")
nwords<-str_count(phrase, pattern=" ")
# A match is found
#{ print(nxtword1(phrase)[1:5, 1])}Output the next word
if ((phrase %in% dat$word1) ){
# print(nxtword1(phrase)[1:5, 1])
answer <-dat %>% filter(word1 == phrase) %>% select(-word1)
# print(answer[1:5, 1])
#print(answer)
}
#No match found. Output the five most common unigrams
if (!(phrase %in% dat$word1) && nwords==0)
{ answer <-(c("the","to", "and", "in", "of"))}
}
answer5 <- answer[1:5, 1]
}
I tried to put answer5 on Shiny. Shiny posted this error message
> shiny::runApp('nextword-app')
Loading required package: shiny
Warning: package ‘shiny’ was built under R version 3.6.1
Listening on http://127.0.0.1:3281
Warning: Error in whatsnexta: object 'answer' not found
98: whatsnexta [helpers.R#33]
96: renderText [C:\Users\mlrob\OneDrive\Documents\nextword-app/app.R#21]
95: func
82: origRenderFunc
81: output$predicted_word
1: shiny::runApp