web-dev-qa-db-fra.com

Quelle est la bonne façon de demander une entrée utilisateur dans un programme R?

Le programme my ci-dessous (qui est en deux parties) fonctionne si je les exécute séparément - c'est-à-dire, si je colle la première partie dans la console R, l'exécute puis colle la seconde et l'exécute. Cependant, ce n'est pas ce que je veux. Je veux exécuter tout le programme en même temps. Si je le fais, cela montre l'erreur suivante dans ma console:

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

J'ai essayé d'identifier le problème mais je n'ai pas pu trouver la cause première. Je serais plus qu'heureux, si quelqu'un pouvait venir à mon aide.

#**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)
31
Son

@Marek a tout à fait raison. Quelques remarques supplémentaires:

  • En général, vous ne devez pas utiliser scan() mais readline() pour cela.
  • Je diviserais le code pour qu'il devienne clair ce qui sert à lire en n et ce qui sert à lire en acr.
  • réfléchissez si vous souhaitez revenir à l'invite lorsque les gens appuient simplement sur Entrée, ou si vous souhaitez poser de nouveau la question jusqu'à ce qu'ils remplissent une valeur correcte.
  • vous pouvez utiliser la puissance de grepl() pour vérifier si l'entrée est au bon format.

Pour inclure les commandes correctes et détecter toutes les erreurs possibles, la construction suivante est beaucoup plus propre et ne cassera pas votre code une fois copiée sur la console:

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
}

Cela montre comment mettre fin à la question lorsque les gens ne remplissent rien. La construction grepl exclut tout caractère qui n'est pas un chiffre, y compris le point.

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))
}

Cela montre comment poser à nouveau la question lorsque les gens ne remplissent rien. Le grepl exclut tout caractère qui n'est pas un chiffre ou un point.

27
Joris Meys

C'est parce que lorsque vous copiez et collez tout, scan lit les lignes collées en entrée.

Si vous copiez cette arborescence sur la console

x <- scan(nmax=1)
1
2

x devenir 1, scan n'attendez pas votre interaction car la ligne a été lue.

Vous devez tout emballer dans {}:

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

Vous devez envelopper les deux parties de votre programme. Pour être plus clair: lorsque vous collez votre code sur la console } devrait être le dernier signe.

9
Marek