2017-03-03 1 views
1

J'ai posté une question sur le codage il y a quelques jours (Need help code mock sampling). J'ai remarqué qu'il peut y avoir trop de contexte. Ainsi, en prolongeant de la poste, je minimise ma question. Toute rétroaction sera grandement appréciée.Besoin d'aide pour le codage (texte minimisé)

J'ai nombres aléatoires comme ceci:

pass.theo <- c(2,4,12,13,14,19,21,27,30,31,32,35,36,38,41,44,49,50,52,57,59,60,61,63,65,68,79,80,86,92,96,100) 

Début du premier numéro (c.-à-2) dans ce cas particulier, je voudrais trouver un nombre qui est le premier numéro qui est 5 ou plus que les éléments précédents (c.-à-d. 2). Dans ce cas, le nombre est 12. Et puis à partir du nombre 12, je veux trouver un autre premier nombre qui est 5 ou plus et continuer jusqu'à la fin. Avec le numéro ci-dessus, j'ai généré manuellement ce code mais j'ai besoin de code pour conduire en général.

tf <- c(
pass.theo[2]-pass.theo[1] > 5, # 
pass.theo[3]-pass.theo[1] > 5, # select 
pass.theo[4]-pass.theo[3] > 5, # 
pass.theo[5]-pass.theo[3] > 5, # 
pass.theo[6]-pass.theo[3] > 5, # select 
pass.theo[7]-pass.theo[6] > 5, # 
pass.theo[8]-pass.theo[6] > 5, # select 
pass.theo[9]-pass.theo[8] > 5, 
pass.theo[10]-pass.theo[8] > 5, 
pass.theo[11]-pass.theo[8] > 5, 
pass.theo[12]-pass.theo[8] > 5, # select 
pass.theo[13]-pass.theo[12] > 5, 
pass.theo[14]-pass.theo[12] > 5, 
pass.theo[15]-pass.theo[12] > 5, # select 
pass.theo[16]-pass.theo[15] > 5, 
pass.theo[17]-pass.theo[15] > 5, # select 
pass.theo[18]-pass.theo[17] > 5, 
pass.theo[19]-pass.theo[17] > 5, 
pass.theo[20]-pass.theo[17] > 5, # select 
pass.theo[21]-pass.theo[20] > 5, 
pass.theo[22]-pass.theo[20] > 5, 
pass.theo[23]-pass.theo[20] > 5, 
pass.theo[24]-pass.theo[20] > 5, # select 
pass.theo[25]-pass.theo[24] > 5, 
pass.theo[26]-pass.theo[24] > 5, 
pass.theo[27]-pass.theo[24] > 5, # select 
pass.theo[28]-pass.theo[27] > 5, 
pass.theo[29]-pass.theo[27] > 5, # select 
pass.theo[30]-pass.theo[29] > 5, # select 
pass.theo[31]-pass.theo[30] > 5, 
pass.theo[32]-pass.theo[30] > 5 # select 
) 
tf 
passes <- c(pass.theo[1], pass.theo[-1][tf]) 

expected.select <- ifelse(pass.theo %in% passes, 'select', 'drop') 
cbind(pass.theo, expected.select) 
     pass.theo expected.select 
# [1,] "2"  "select"  
# [2,] "4"  "drop"   
# [3,] "12"  "select"  
# [4,] "13"  "drop"   
# [5,] "14"  "drop"   
# [6,] "19"  "select"  
# [7,] "21"  "drop"   
# [8,] "27"  "select"  
# [9,] "30"  "drop"   
#[10,] "31"  "drop"   
#[11,] "32"  "drop"   
#[12,] "35"  "select"  
#[13,] "36"  "drop"   
#[14,] "38"  "drop"   
#[15,] "41"  "select"  
#[16,] "44"  "drop"   
#[17,] "49"  "select"  
#[18,] "50"  "drop"   
#[19,] "52"  "drop"   
#[20,] "57"  "select"  
#[21,] "59"  "drop"   
#[22,] "60"  "drop"   
#[23,] "61"  "drop"   
#[24,] "63"  "select"  
#[25,] "65"  "drop"   
#[26,] "68"  "drop"   
#[27,] "79"  "select"  
#[28,] "80"  "drop"   
#[29,] "86"  "select"  
#[30,] "92"  "select"  
#[31,] "96"  "drop"   
#[32,] "100"  "select" 

Je veux toujours inclure le premier élément et sélectionner tf == TRUE à partir du reste de pass.theo.

passes 

Existe-t-il un moyen de créer une fonction ci-dessus?

Merci beaucoup d'avance !!!

+3

* " trouver des chiffres à 5 ou plus que les éléments précédents "* serait simplement' diff (pass.theo)> 5', mais cela ne correspond pas à votre code. On dirait que votre logique est un peu plus compliquée que ça. – r2evans

+0

Il semble donc que l'indice soustrait change quand un calcul retourne VRAI. –

+0

Merci pour vos commentaires. J'ai essayé de clarifier plus ci-dessus. Par exemple, si je trouve un premier nombre (c.-à-d., 12) qui est 5 ou plus grand que le nombre, 2. Ensuite, je veux le répéter du nombre, 12 de sorte que le prochain numéro soit 19 et ainsi de suite. – Steve

Répondre

2
pass.theo <- c(2,4,12,13,14,19,21,27,30,31,32,35,36,38,41,44,49,50,52,57,59,60,61,63,65,68,79,80,86,92,96,100) 
# to keep the original pass.theo untouched 
dat <- pass.theo 
for (i in seq_along(pass.theo)[-1]) { 
    if ((dat[i] - dat[i-1]) < 5) dat[i] <- dat[i-1] 
} 
ret <- c(FALSE, diff(dat) >= 5) 

Pour la démonstration, je vais les lier afin que vous puissiez voir ce qui est arrivé:

data.frame(pass.theo = pass.theo, mod = dat, ret = ret) 
# pass.theo mod ret 
# 1   2 2 FALSE 
# 2   4 2 FALSE 
# 3   12 12 TRUE 
# 4   13 12 FALSE 
# 5   14 12 FALSE 
# 6   19 19 TRUE 
# 7   21 19 FALSE 
# 8   27 27 TRUE 
# 9   30 27 FALSE 
# 10  31 27 FALSE 
# 11  32 32 TRUE 
# 12  35 32 FALSE 
# 13  36 32 FALSE 
# 14  38 38 TRUE 
# 15  41 38 FALSE 
# 16  44 44 TRUE 
# 17  49 49 TRUE 
# 18  50 49 FALSE 
# 19  52 49 FALSE 
# 20  57 57 TRUE 
# 21  59 57 FALSE 
# 22  60 57 FALSE 
# 23  61 57 FALSE 
# 24  63 63 TRUE 
# 25  65 63 FALSE 
# 26  68 68 TRUE 
# 27  79 79 TRUE 
# 28  80 79 FALSE 
# 29  86 86 TRUE 
# 30  92 92 TRUE 
# 31  96 92 FALSE 
# 32  100 100 TRUE 

Je ne suis pas fan de changer itérativement le vecteur comme ça, mais je ne sais pas d'autres outils qui roulent le long du vecteur correctement.

Edit:

En fait, en prenant l'inspiration de @Reduce de MrFlick (aurait pensé), vous pouvez remplacer la boucle for avec:

dat2 <- Reduce(function(a,b) if ((b-a)<5) a else b, 
       pass.theo, accumulate = TRUE) 

Puis

c(FALSE, diff(dat2) >= 5) 

est le même que mon ret ci-dessus. (Je ne suis pas en train de voler @ la réponse de MrFlick, il devrait prendre le crédit pour suggérer Reduce sur ma boucle for bâclée/inefficace.

+1

Vous avez vraiment nettoyé l'appel Réduire donc j'approuve totalement. – MrFlick

+1

Je penche souvent vers 'zoo :: rollapply' d'abord pour quelque chose comme, mais il ne s'accumule pas * comme je l'espère. J'ai l'impression que 'Reduce (..., accumulate = TRUE)' est tellement une fonction de roulement sous-estimée avec cet argument. (Le fait que 'Reduce' fasse une boucle' for' sous le capot est une technicité que je vais devoir accepter :-) – r2evans

+0

Hi r2evans. C'est bien!!! Je vais devoir passer du temps à comprendre votre code. Merci beaucoup pour vos aides et tous les autres pour les commentaires !!! – Steve

2

Voici une méthode utilisant Reduce()

pp<-which(sapply(Reduce(function(a,b) { 
    aa <- a[[1]] 
    if (b-aa>5) { 
     return(list(b, T)) 
    } else { 
     return(list(aa, F)) 
    } 
}, pass.theo, init=list(pass.theo[1],F), accumulate=T), `[[`, 2)) - 1 
passes <- c(pass.theo[1], pass.theo[pp]) 

Fondamentalement, j'utilisé Reduce() à l'étape pairwise à travers les éléments en passant la valeur la plus basse actuelle puis j'utilise sapply() pour extraire les valeurs où un changement est survenu et utiliser which() pour obtenir les index (en soustrayant 1 car j'ai utilisé une valeur initiale dans l'appel Reduce)

+0

Merci beaucoup pour votre aide, MrFlick !!! – Steve