2011-08-05 20 views
5

he conseguido escribir una for loop para comparar las cartas en el siguiente vector:comparar los elementos adyacentes del mismo vector (bucles evitando)

bases <- c("G","C","A","T") 
test <- sample(bases, replace=T, 20) 

test volverá

[1] "T" "G" "T" "G" "C" "A" "A" "G" "A" "C" "A" "T" "T" "T" "T" "C" "A" "G" "G" "C" 

con la función Comp() I puede verificar si una letra coincide con la siguiente letra

Comp <- function(data) 
{ 
    output <- vector() 
    for(i in 1:(length(data)-1)) 
    { 
    if(data[i]==data[i+1]) 
     { 
     output[i] <-1 
     } 
     else 
     { 
     output[i] <-0 
     } 
    } 
    return(output) 
} 

Resultando en;

> Comp(test) 
[1] 0 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 1 0 

Esto funciona, pero es muy lento con grandes cantidades. Para ello he intentado sapply()

Comp <- function(x,i) if(x[i]==x[i+1]) 1 else 0 
unlist(lapply(test, Comp, test)) 

Desafortunadamente no su trabajo ... (Error in i + 1 : non-numeric argument to binary operator) tengo problemas para averiguar cómo acceder a la letra precedente en el vector para compararlo. También el length(data)-1, para "no comparar" la última letra podría convertirse en un problema.

¡Gracias a todos por la ayuda!

Saludos Lucky

+0

Reformulé el título para ilustrar mejor el problema y como referencia. También debe tener en cuenta que sapply/lapply etc. * son * loops, aunque en una forma diferente. Ver también http: // stackoverflow.com/questions/2275896/is-rs-apply-family-more-than-syntactic-sugar –

+0

Gracias, soy nuevo en R y en programación y no estoy familiarizado con los términos – LuckyLion

Respuesta

13

Justo "retraso" test y utilizar ==, que se vectorizado.

bases <- c("G","C","A","T") 
set.seed(21) 
test <- sample(bases, replace=TRUE, 20) 
lag.test <- c(tail(test,-1),NA) 
#lag.test <- c(NA,head(test,-1)) 
test == lag.test 

Actualización:

Además, su función Comp es lento porque no se especifica la duración de output cuando se inicialice. Sospecho que estabas tratando de preasignar, pero vector() crea un vector de longitud cero que debe expandirse durante cada iteración de tu ciclo. Su función Comp es significativamente más rápida si cambia la llamada a vector() a vector(length=NROW(data)-1).

set.seed(21) 
test <- sample(bases, replace=T, 1e5) 
system.time(orig <- Comp(test)) 
# user system elapsed 
# 34.760 0.010 34.884 
system.time(prealloc <- Comp.prealloc(test)) 
# user system elapsed 
# 1.18 0.00 1.19 
identical(orig, prealloc) 
# [1] TRUE 
+0

Muchas gracias =) – LuckyLion

3

Como escribió @Joshua, debe utilizar la vectorización, por supuesto, es mucho más eficiente. ... Pero solo como referencia, su función Comp aún se puede optimizar un poco.

El resultado de una comparación es TRUE/FALSE que es versiones glorificadas de 1/0. Además, garantizar que el resultado sea entero en lugar de numérico consume la mitad de la memoria.

Comp.opt <- function(data) 
{ 
    output <- integer(length(data)-1L) 
    for(i in seq_along(output)) 
    { 
     output[[i]] <- (data[[i]]==data[[i+1L]]) 
    } 
    return(output) 
} 

... y la diferencia de velocidad:

> system.time(orig <- Comp(test)) 
    user system elapsed 
    21.10 0.00 21.11 
> system.time(prealloc <- Comp.prealloc(test)) 
    user system elapsed 
    0.49 0.00 0.49 
> system.time(opt <- Comp.opt(test)) 
    user system elapsed 
    0.41 0.00 0.40 
> all.equal(opt, orig) # opt is integer, orig is double 
[1] TRUE 
+0

Gracias por la ¡sugerencia! – LuckyLion

0

Tener un vistazo a esto:

> x = c("T", "G", "T", "G", "G","T","T","T") 
> 
> res = sequence(rle(x)$lengths)-1 
> 
> dt = data.frame(x,res) 
> 
> dt 
    x res 
1 T 0 
2 G 0 
3 T 0 
4 G 0 
5 G 1 
6 T 0 
7 T 1 
8 T 2 

podría funcionar más rápido.

Cuestiones relacionadas