Как правильно запрашивать ввод пользователя в R-программе? - PullRequest
31 голосов
/ 12 мая 2011

Моя программа ниже (которая состоит из двух частей) работает, если я запускаю их отдельно - то есть, если я вставляю первую часть в консоль R, запускаю ее, а затем вставляю вторую и запускаю ее.Однако я не хочу этого.Я хочу запустить всю программу сразу.Если я это сделаю, в консоли отобразится следующая ошибка:

1: 
Read 0 items
1: 
Read 0 items
Error in while ((n <= 0) | (acr <= 0) | (acr >= 1)) { : 
  argument is of length zero

Я попытался определить проблему, но не смог найти основную причину.Я был бы более чем рад, если бы кто-то мог прийти мне на помощь.

#**FIRST PART OF THE PROGRAM**

n <- -2
acr <- -2
while((n<=0) | (acr<=0) | (acr>=1)) {
   print("enter a  positive integer and the average cancellation rate between 0 and 1  
                you want")
   try(n <- scan(what=integer(), nmax=1), silent=TRUE)
   try(acr <- scan(what=double(), nmax=1), silent=TRUE)
}


#**SECOND PART OF THE PROGRAM**

bygrace <- read.table("C:\\MyRfolder\\bygrace.txt", header=FALSE)
r <- nrow(bygrace)
c <- ncol(bygrace)
copybygrace <- array(bygrace, dim=c(r, c))
copybygrace <- bygrace[-((n+1):r), ]
write.table(copybygrace,file="C:\\MyRfolder\\copybygrace.txt", sep="\t")
copybygrace <- read.table("C:\\MyRfolder\\copybygrace.txt", header=TRUE)

Ответы [ 2 ]

27 голосов
/ 12 мая 2011

@ Марек очень прав.Еще несколько замечаний:

  • В общем, вы не должны использовать scan(), но readline() для этого.
  • Я бы разделил код, чтобы стало ясно, что служит для чтения в n, а что для чтения в acr.
  • подумайте, хотите ли вы вернуться к приглашению, когда люди простонажмите ввод или хотите ли вы повторно задать вопрос до тех пор, пока они не введут какое-то правильное значение.
  • Вы можете использовать мощность grepl(), чтобы проверить, является ли ввод правильным форматом.

Чтобы включить правильные элементы управления и перехватить все возможные ошибки, следующая конструкция намного чище и не нарушит ваш код при копировании на консоль:

while(n < 1 ){
  n <- readline("enter a positive integer: ")
  n <- ifelse(grepl("\\D",n),-1,as.integer(n))
  if(is.na(n)){break}  # breaks when hit enter
}

Это показывает, как завершить вопроскогда люди ничего не заполняют.Конструкция grepl исключает любой символ, который не является цифрой, включая точку.

while(is.na(acr) | acr <= 0 | acr >= 1 ){
  acr <- readline("and the average cancellation rate between 0 and 1 :")
  acr <- ifelse(grepl("[^0-9.]",acr),-1,as.numeric(acr))
}

Это показывает, как повторно задать вопрос, когда люди ничего не заполняют.Grepl исключает любой символ, который не является цифрой или точкой.

9 голосов
/ 12 мая 2011

Это потому, что когда вы копируете и вставляете все, тогда scan читает вставленные строки как ввод.

Если вы скопируете строки этого дерева в консоль

x <- scan(nmax=1)
1
2

x становится 1, scan не ждите вашего взаимодействия, потому что оно получило строку для чтения.

Вы должны обернуть все в {}:

{
 x <- scan(nmax=1)
 1
 2
}

Вы должны обернуть обе части вашей программы. Чтобы быть более понятным: при вставке кода в консоль } должен быть последним знаком.

...