Search code examples
rjupyter-notebookjupyterjupyter-irkernel

How to key in "Yes" or "No" in Jupyter notebook


I already referred this post and this post. But it doesn't solve my problem. Please don't mark it as duplicate

I am trying to run the below piece of code in Jupyter Notebook with R kernel.

model_predictors <- buildModel(flag, fv_full_data, outcomeName, folder)

I get an error message like below

Model about to be built   # this is log message and not error

1 package is needed for this model and is not installed. (randomForest). Would you like to try to install it now?    # here I see that it asks for a question but without my input it selects `No`
Error: Required package is missing
Traceback:

1. buildModel(flag, fv_full_data, outcomeName, folder)
2. train(x = trainDF[, predictorsNames], y = factor(trainLabels), 
 .     method = "rf", metric = "Fscore", trControl = objControl, 
 .     tuneGrid = rf_grid, preProcess = c("center", "scale"))
3. train.default(x = trainDF[, predictorsNames], y = factor(trainLabels), 
 .     method = "rf", metric = "Fscore", trControl = objControl, 
 .     tuneGrid = rf_grid, preProcess = c("center", "scale"))
4. checkInstall(models$library)
5. stop("Required package is missing", call. = FALSE)

How can I avoid this error and prevent jupyter selecting No as default for dynamic prompts?


Solution

  • In your example, you actually never reach the part of code that handles input. These inputs only occur for interactive sessions - which Jupyter is not. You can check with

    interactive()
    #> FALSE
    
    menu(c("yes", "no"))
    #> Error in menu(c("yes", "no")): menu() cannot be used non-interactively
    #> Traceback:
    #> 
    #> 1. menu(c("yes", "no"))
    #> 2. stop("menu() cannot be used non-interactively")
    

    caret::checkInstall prints out the message "Would you like to try to install x now?", but it will only accept input for interactive sessions.

    Here is the code for caret::checkInstall with my comments.

    function (pkg) 
    {
        good <- rep(TRUE, length(pkg))
        for (i in seq(along = pkg)) {
            tested <- try(find.package(pkg[i]), silent = TRUE)
            if (inherits(tested, "try-error")) 
                good[i] <- FALSE
        }
        if (any(!good)) {
            pkList <- paste(pkg[!good], collapse = ", ")
            msg <- paste(sum(!good), ifelse(sum(!good) > 1, " packages are", 
                " package is"), " needed for this model and", 
                ifelse(sum(!good) > 1, " are", " is"), 
                " not installed. (", pkList, "). Would you like to try to install", 
                ifelse(sum(!good) > 1, " them", " it"), 
                " now?", sep = "")
            cat(msg) # Print the message
            if (interactive()) { # In Jupyter, `interactive()` is `FALSE`.
                bioc <- c("affy", "logicFS", "gpls", 
                    "vbmp")
                installChoice <- menu(c("yes", "no")) # This is where it gets input
                if (installChoice == 1) {
                    hasBioc <- any(pkg[!good] %in% bioc)
                    if (!hasBioc) {
                      install.packages(pkg[!good])
                    }
                    else {
                      inst <- pkg[!good]
                      instC <- inst[!(inst %in% bioc)]
                      instB <- inst[inst %in% bioc]
                      if (length(instC) > 0) 
                        install.packages(instC)
                      biocLite <- NULL
                      source("http://bioconductor.org/biocLite.R")
                      biocLite(instB)
                    }
                }
                else stop("Required package is missing", call. = FALSE)
            }
            else stop("Required package is missing", call. = FALSE) # Because `interactive()` is `FALSE`, this `stop` is called
        }
    }
    

    For your situation, install.packages("randomForest") is the best option.

    If you were in RStudio, you could use the rstudioapi like this

    f <- function() {
      rstudioapi::sendToConsole("1")
      menu(c("yes", "no"))
    }
    f()
    #> 1: yes
    #> 2: no
    #> 
    #> Selection: 1
    #> [1] 1