2017-12-30 9 views
2

Überspringen Sage, ich habe diesen Vektor:Extrahieren von Elementen aus einem Vektor, während eine feste Anzahl von Elementen

a <- round(runif(100, 0, 1), digits = 0) 

ich das erste Element in dem Vektor finden möchte, dass die Nummer 1 enthält Danach Element gefunden wird, Überspringe 3 Elemente (auch wenn sie 1 enthalten), finde dann das nächste Element, das 1 enthält und wiederhole das Finden von 1 und das Überspringen von 3 Elementen nach dem Finden von 1s.

Meine gewünschte Ausgabe sind die Zeilennummern für das erste Element, das 1 enthält, gefolgt von dem Rest der Zeilennummern, die 1 enthalten, nach Berücksichtigung der übersprungenen Elemente.

Antwort

0

Vielleicht eine while Schleife?

set.seed(123) 
a <- round(runif(100,0,1), digits =0) 
n <- length(a) 
ind_less_n <- 1 
i <- 1 
index_save <- numeric(n) 
while(ind_less_n){ 
    if(a[i] == 1){ 
    index_save[i] <- 1 
    i <- i + 4 
    } else { 
    i <- i + 1 
    } 
    if(i > n) ind_less_n <- 0 
} 
head(cbind(a, index_save), 20) 
     a index_save 
[1,] 0   0 
[2,] 1   1 
[3,] 0   0 
[4,] 1   0 
[5,] 1   0 
[6,] 0   0 
[7,] 1   1 
[8,] 1   0 
[9,] 1   0 
[10,] 0   0 
[11,] 1   1 
[12,] 0   0 
[13,] 1   0 
[14,] 1   0 
[15,] 0   0 
[16,] 1   1 
[17,] 0   0 
[18,] 0   0 
[19,] 0   0 
[20,] 1   1 

Sie können die Zeilennummern extrahieren mit which(index_save == 1)

+0

Right ... geändert, um die i + 3 bis i + 4. – jrlewi

1

Ich glaube nicht, dass Sie dies tun können, um eine Art Schleife ohne Rückgriff. Hier ist eine Möglichkeit, es zu tun. 1. Wir bekommen einen Vektor von Positionen von allen. Dann finden wir wiederholt das erste Element dieses Vektors, das 3 oder weniger von dem vorherigen ist und es aus der Liste entfernt. Wiederholen Sie dies, bis Sie alle diejenigen entfernt haben, die zu nah an ihrem Vornamen sind.

x = which(a==1) 
repeat { 
    to.remove = which(diff(x) <= 3)[1] + 1 
    if (is.na(to.remove)) break 
    x = x[-to.remove] 
} 

Wenn Sie mit sehr großen Vektoren zu tun hat, kann es effizientere Wege, dies zu tun, und vielleicht RCPP betrachten, wenn die Geschwindigkeit ist ein Problem.

0

Sie könnten Reduce mit accumulate = TRUE oder purrr::accumulate verwenden, obwohl Sie über eine Liste mit separaten Elementen für das Ergebnis und die Anzahl der Übersprungen, z.

library(tidyverse) 
set.seed(47) 

df_ones <- data_frame(a = rbinom(100, 1, .5), # make sample data 
         is_one = a, # initialize result and count 
         count = NA) %>% 
    split(seq(nrow(.))) %>% # split into list of one-row data frames 
    accumulate( # for each sequential pair of elements, return and pass on a list of... 
     ~list(a = .y$a, # the original value for checking, 
       is_one = if(.x$count <= 3) 0 else .y$is_one, # the result, changing 1 to 0 where required, and 
       # the count since a 1, resetting when a 1 is kept 
       count = if(.x$count > 3 & .y$is_one) { 
        1 
       } else { 
        .x$count + 1 
       }), 
     .init = list(a = NA, is_one = 0, count = 4) # set initial .x value 
    ) %>% 
    bind_rows() %>% # collapse resulting list to data frame 
    slice(-1) # remove row for initializing value 

df_ones 
#> # A tibble: 100 x 3 
#>  a is_one count 
#> <int> <dbl> <dbl> 
#> 1  1  1  1 
#> 2  0  0  2 
#> 3  1  0  3 
#> 4  1  0  4 
#> 5  1  1  1 
#> 6  1  0  2 
#> 7  0  0  3 
#> 8  0  0  4 
#> 9  1  1  1 
#> 10  1  0  2 
#> # ... with 90 more rows 

die Indizes zu extrahieren,

df_ones %>% 
    pull(is_one) %>% # extract result as vector 
    as.logical() %>% # coerce to Boolean 
    which() # get indices of TRUE values 
#> [1] 1 5 9 14 22 29 35 40 44 48 52 56 61 66 71 75 79 84 88 93 97 
Verwandte Themen