2016-03-08 17 views
6

bundan varsayalım 1 ve 0 bir sekansı içeren bir vektör, uzunluğu 166 olan ve bu ayıklamak için istiyorum Şimdibulma Alt vektör 0 '

y <- c(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1, 1,1,1,1,1,0,1,1,0,1,0,1,0,0,0,0,0,1,0,0,0,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 
1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1, 
1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,0,0,0,0,0,1,1,1,1) 

olduğu Bu iki özellik

sağlayacağı şekilde, vektör üzerinden bir en uzun alt vektör

(1) alt vektör 1'den başlar ve toplam 1.

(2) Bu içerebilir% 5'e kadar ihtiva sıfırlarla sona ermelidir alt vektörün uzunluğu.

rle işleviyle başlattım. Her adımda 1 ve 0 sayar. Bana 74 + 2 + 17 + 1 + 2 + 3 = 99 bu gerekli alt dizisini içerir Bu durumda

> d 
    value length 
1  1  22 
2  0  1 
3  1  13 
4  0  1 
5  1  2 
6  0  1 
7  1  1 
8  0  1 
9  1  1 
10  0  5 
11  1  1 
12  0  3 
13  1  2 
14  0  1 
15  1  1 
16  0  1 
17  1  74 
18  0  2 
19  1  17 
20  0  1 
21  1  2 
22  0  1 
23  1  3 
24  0  5 
25  1  4 

verir

z <- rle(y) 
d <- data.frame(z$values, z$lengths) 
colnames(d) <- c("value", "length") 

gibi yüzden olacak 2+ 1 + 1 = 4 sıfır, 99'un% 5'inden azdır. Eğer ileriye doğru hareket edersek ve sıra 99 + 5 + 4 = 108 olacak ve sıfırlar 4 + 5 = 9 olacak, bu da 108'in% 5'inden daha fazla olacaktır.

+0

Sanırım subvektörünüz aslında 100'dür (74 + 2 + 17 + 1 + 2 + 1 + 3). – josliber

cevap

4

Bu vektörün çalışma uzunluğu kodlamasını hesaplayarak çok yakınsınız. Tüm kalanlar, 1'lerin tüm çiftlerini göz önünde bulundurmak ve en uzun uzunluktaki çifti seçmek ve "% 5'ten fazla sıfır" kuralına uymaktır.

ones <- which(d$value == 1) 
# pairs holds pairs of rows in d that correspond to runs of 1's 
if (length(ones) >= 2) { 
    pairs <- rbind(t(combn(ones, 2)), cbind(ones, ones)) 
} else if (length(ones) == 1) { 
    pairs <- cbind(ones, ones) 
} 

# Taking cumulative sums of the run lengths enables vectorized computation of the lengths 
# of each run in the "pairs" matrix 
cs <- cumsum(d$length) 
pair.length <- cs[pairs[,2]] - cs[pairs[,1]] + d$length[pairs[,1]] 
cs0 <- cumsum(d$length * (d$value == 0)) 
pair.num0 <- cs0[pairs[,2]] - cs0[pairs[,1]] 

# Multiple the length of a pair by an indicator for whether it's valid and take the max 
selected <- which.max(pair.length * ((pair.num0/pair.length) <= 0.05)) 
d[pairs[selected,1]:pairs[selected,2],] 
# value length 
# 15  1  1 
# 16  0  1 
# 17  1  74 
# 18  0  2 
# 19  1  17 
# 20  0  1 
# 21  1  2 
# 22  0  1 
# 23  1  3 

Biz aslında bir o biraz daha uzun olarak subvector bulundu: Bu rle çıkışından ishal uzunluklarını almak için 1'ler ve cumsum ishal tüm çiftleri hesaplamak için combn kullanarak tamamen vektörleşen şekilde yapılabilir OP tarafından bulundu: 102 eleman ve beş 0 (% 4.90) var.

+0

Teşekkürler josliber, Gerçekten çok yardımcı oldu ve evet doğru cevap 102'dir. – Pankaj

+0

Aynı şeyi tarakla da yapabilirsiniz: 'r = rle (y); w1 = hangisi (r $ değerler == 1); v = taranmış (w1, 2, FUN = işlev (i) ile ((l, \ '[\', i [1]: i [2]), { toplamı (uzunlukları) * (toplam (uzunluklar [ değerler == 1])> .95 * toplam (uzunluklar)) })); comb (w1,2) [, hangi.max (v)] ' – Frank

+1

@Frank evet, çok büyük vektörler için, vektörel işlemlerin kullanılmasından önemli bir performans artışı elde etmem ve her bir satır çiftinden döngü yapmamayı ve bunları ayrı ayrı işlememem gerektiğini . Ayrıca "tarak" (i, i) çiftlerini (başlangıç ​​ve bitiş sırası aynıdır) vermez. Bu, seçilen altkümede asla 0 içermememiz gereken bir vektör olsaydı önemlidir (ör. - c (1, 0, 1) '). – josliber