2017-01-27 4 views
0

Je sais qu'il y a déjà de nombreuses questions sur les boucles while dans R, mais j'ai regardé la plupart d'entre elles et aucune ne semble résoudre ce problème.Écrire une boucle while imbriquée dans R

J'exécute une étude de simulation sur une variable (vanq) qui ne peut pas être simulée avec précision. Ainsi, au lieu de générer aléatoirement des valeurs de vanq pour deux groupes puis de tester la robustesse de divers tests, j'utilise un grand ensemble de données d'observations vanq et j'attribue aléatoirement des groupes (essentiellement en faisant la même chose, mais en arrière). Pour ce faire correctement, je dois générer des groupes qui se réunissent toutes les conditions suivantes:

  1. Les valeurs vanq moyennes de chaque groupe diffèrent de moins de 0,0001
  2. valeurs de chaque groupe de la médiane diffèrent de moins de 0,0001 (0) de façon optimale
  3. les trois tests que j'utilise tous donnent p.values> 0,5

jusqu'à présent, le code que j'ai est ceci:

#generate two random groups of equal size 
mydata$X.5.NS = rbinom(nrow(mydata),1,0.5) 

while(

    #any of the tests give p.values less than 0.5 
    min(
     t.test(mydata$vanq~mydata$X.5.NS, var.equal = TRUE)$p.value, 
     t.test(mydata$vanq~mydata$X.5.NS, var.equal = FALSE)$p.value, 
     wilcox.test(mydata$vanq~mydata$X.5.NS)$p.value) < 0.5 | 

    # or the means differ by more than 0.0001 
    abs(mean(mydata$vanq[ mydata$X.5.NS == 0]) - 
     mean(mydata$vanq[ mydata$X.5.NS == 1])) > 0.0001 | 

    #or the medians differ by more than 0 
    abs(median(mydata$vanq[ mydata$X.5.NS == 0]) - 
     median(mydata$vanq[ mydata$X.5.NS == 1])) > 0 
) 

{ 
#re-assign the random groups 
mydata$X.5.NS = rbinom(nrow(mydata),1,0.5) 
} 

Cependant, il faut plus d'une heure pour répondre à ces conditions, car il faut environ 12 secondes pour obtenir les valeurs p et quelques centaines d'essais pour répondre à toutes les conditions. Normalement je le laisserais fonctionner, mais je dois le faire pour trois groupes de plus, et ensuite faire la même procédure mais jusqu'à ce que les moyennes diffèrent de> 1, les médianes diffèrent de> 1, et toutes les valeurs p sont < 0.05, ce qui prend beaucoup plus de temps.

Ce que je voudrais faire est quelque chose comme ceci:

while(
#the means differ by more than 0.0001 
    abs(mean(mydata$vanq[ mydata$X.5.NS == 0]) - 
     mean(mydata$vanq[ mydata$X.5.NS == 1])) > 0.0001 | 

    #or the medians differ by more than 0 
    abs(median(mydata$vanq[ mydata$X.5.NS == 0]) - 
     median(mydata$vanq[ mydata$X.5.NS == 1])) > 0 
) 

{ 
#re-assign the random groups 
mydata$X.5.NS = rbinom(nrow(mydata),1,0.5) 
} 

#once the above conditions have been met, then perform the tests, 
if(min(
     t.test(mydata$vanq~mydata$X.5.NS, var.equal = TRUE)$p.value, 
     t.test(mydata$vanq~mydata$X.5.NS, var.equal = FALSE)$p.value, 
     wilcox.test(mydata$vanq~mydata$X.5.NS)$p.value) < 0.5) 
{ 
#if any of the p.values were > 0.5, go back to the top of the while loop  
} 

L'idée est qu'en testant une seule fois la moyenne et les conditions médianes ont été respectées, je peux accélérer ce processus beaucoup. J'ai essayé d'ajouter divers autres contrôles de flux (if, break, next, etc.) sans chance. Ce dont j'ai vraiment besoin, c'est d'une commande go to line, mais cela ne semble pas exister en R. Toute aide est grandement appréciée.

Here's a flow chart of the process I'm trying to code.

Répondre

0

Je suis honnêtement pas sûr de votre flux de contrôle est peut-être, mais c'est ce que vous avez besoin?

while (min(t.test(mydata$vanq~mydata$X.5.NS, var.equal = TRUE)$p.value, 
      t.test(mydata$vanq~mydata$X.5.NS, var.equal = FALSE)$p.value, 
      wilcox.test(mydata$vanq~mydata$X.5.NS)$p.value) < 0.5)) { 
    while (
     # the means differ by more than 0.0001 
     abs(mean(mydata$vanq[ mydata$X.5.NS == 0]) - 
     mean(mydata$vanq[ mydata$X.5.NS == 1])) > 0.0001 || 

     # or the medians differ by more than 0 
     abs(median(mydata$vanq[ mydata$X.5.NS == 0]) - 
     median(mydata$vanq[ mydata$X.5.NS == 1])) > 0 
    ) { 
     # re-assign the random groups 
     mydata$X.5.NS = rbinom(nrow(mydata), 1, 0.5) 
    } 
} 

L'ensemble peut être rendu plus lisible en enveloppant les tests appels de fonction:

while (any_significant_p_value(mydata, alpha = 0.05)) { 
    while (mean_difference(mydata) > 0.0001 || median_difference(mydata) > 0) { 
     mydata = mydata$X.5.NS = rbinom(nrow(mydata), 1, 0.5) 
    } 
} 
+0

Fermer. Avec cela, il s'arrête une fois que les valeurs p sont> 0,5 et n'évalue pas les différences moyennes ou médianes. – JRF1111

+0

@ JRF1111 Dans ce cas, je pense que le seul recours est d'évaluer * toutes * les conditions dans la même tête de boucle. Cependant, vous pouvez/devriez utiliser des opérateurs logiques en court-circuit '&&' et '||' à la place des opérateurs non court-circuités, '|' et '&'. De cette façon, seules les conditions nécessaires sont évaluées: Si le premier test réussit déjà, le reste n'a pas besoin d'être testé pour '||'. –

+0

c'est dommage. Eh bien, je suppose que je vais juste laisser courir pendant un jour (ou deux). RE les opérateurs logiques court-circuités, je veux réellement que toutes les conditions soient rencontrées. – JRF1111