2011-08-05 19 views
5

udało mi się napisać for loop porównać litery w następujący wektor:porównać sąsiadujących elementów tego samego wektora (pętle unikając)

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

test powróci

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

z funkcją Comp() I może sprawdzić, czy litera pasuje do następnej litery:

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

Wynik w;

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

To działa, ale jego wersja jest wolna i zawiera duże liczby. Nich próbowałem sapply()

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

Niestety jej nie działa ... (Error in i + 1 : non-numeric argument to binary operator) Mam problemy ze zorientowaniem się, jak uzyskać dostęp do poprzedzającego nas w wektorze aby je porównać. Również length(data)-1, aby "nie porównywać" ostatniej litery, może stać się problemem.

Dziękuję wszystkim za pomoc!

Cheers szczęście

+0

Zmieniłem tytuł, aby lepiej zilustrować problem i dla celów porównawczych. Powinieneś także pamiętać, że sapply/lapply itp. * Są * pętle, aczkolwiek w innej formie. Zobacz także http: // stackoverflow.com/questions/2275896/is-rs-apply-family-więcej niż syntaktyczny-cukier –

+0

Dziękuję, jestem nowy w R i programowaniu i nieznajomym w warunkach – LuckyLion

Odpowiedz

13

Po prostu "lag" test i używać ==, który jest wektorowy.

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 

Aktualizacja:

Również czynność Comp jest powolny, ponieważ nie określić długość output kiedy go zainicjować. Podejrzewam, że próbowałeś wstępnie przydzielić, ale vector() tworzy wektor o zerowej długości, który musi zostać rozwinięty podczas każdej iteracji twojej pętli. Twoja funkcja Comp jest znacznie szybsza, jeśli zmienisz połączenie na vector() na 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

Bardzo dziękuję =) – LuckyLion

3

Jak napisał @Joshua, powinieneś używać wektoryzacji - jest to o wiele bardziej wydajne. ... Ale dla przypomnienia, twoja funkcja Comp może być nieco zoptymalizowana.

Wynikiem porównania jest TRUE/FALSE, który jest gloryfikowaną wersją 1/0. Ponadto zapewnienie, że wynik jest liczbą całkowitą zamiast liczbową, pochłania połowę pamięci.

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

... a różnica prędkości:

> 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

Dziękuję za sugestia! – LuckyLion

0

rzucić okiem na to:

> 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 

może działać szybciej.

Powiązane problemy