2014-11-13 35 views
5

L'obiettivo è controllare se il valore di indice i è 1 e quindi apportare le precedenti sei voci come 1.Come costruire questa variabile binaria in R?

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

## Required output 
y <- c(1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1) 

## Attempt 
for(j in seq_along(x)){ 
if(x[j] == 1){ 
    for(i in (j-6):j) 
    x[i] = 1 
    }} 

Potrebbe aiutare a risolvere questo o meglio approccio?

Grazie.

risposta

3

utilizzo 'per' ciclo:

ddf = data.frame(x,y=0) 
for(i in 1:nrow(ddf)){ 
    if(ddf[i,'x']==1){ 
     j = i-5 
     if(j<1) j=1 
     ddf[j:i,'y'] = 1 
    } 
} 
ddf 
    x y 
1 0 1 
2 0 1 
3 0 1 
4 1 1 
5 0 0 
6 0 0 
7 0 0 
8 0 0 
9 0 0 
10 0 0 
11 0 0 
12 0 1 
13 0 1 
14 0 1 
15 0 1 
16 0 1 
17 1 1 
18 0 1 
19 1 1 

y = ddf$y 
y 
[1] 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 
+0

Grazie per la risposta. Potresti spiegare perché il mio ciclo stava restituendo il vettore y come tutti gli 1. Perché ho bisogno di un dataframe qui? – Anusha

+0

Non si stava correggendo se j-6 era inferiore a 1. Anche data.frame è più facile da lavorare. – rnso

+0

+1. Sarebbe possibile metterlo in una funzione e poi usare apply? È solo curioso di sapere come si definirebbe la parola sapply o lapply per questo ciclo. – Anusha

2
y<-x 
y[unlist(sapply(which(x==1), 
       function(val){ 
        val:(max(val-6,1)) 
       } 
       ) 
     ) 
    ]<-1 

> y 
[1] 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 

Spiegazione:

ho guardo per gli indici di x = 1 con which(x==1). Quindi, per ciascuno degli indici ottengo gli indici da quello con x = 1 al sesto prima di quello con sapply(...) quindi non elenco il risultato per avere solo un vettore di indici per cui y deve essere 1. Ho quindi assegnato 1 a i corrispondenti valori y

un altro scritto, in 2 fasi:

y<-x 
ind<-unlist(sapply(which(x==1),function(val){val:(max(val-6,1))})) 
y[ind]<-1 

> y 
[1] 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0

Grazie per la risposta. Potresti spiegare come hai definito la funzione. Stavo cercando un approccio * apply. Come funziona quella parte '<- 1'? – Anusha

+0

@Anusha, ho modificato la mia risposta per aggiungere una spiegazione, dimmi se è tutto ok ora o se hai bisogno che io dettagli un po 'di più. – Cath

+0

Ho capito quella parte. Sono curioso di sapere {val: (max (val-6,1))}))] <- 1, la parentesi e la logica. – Anusha

5

si potrebbe provare le seguenti opzioni (anche se non dimenticate di inizializzare x quando si cerca ogni opzione come sto ignorando esso)

indx <- mapply(function(x, y) x:y, which(x == 1) - 6 , which(x == 1)) 
x[indx[indx > 0]] <- 1 
x 
## [1] 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 

O ancora più semplice

indx <- sapply(which(x == 1) - 6, function(x) x:(x + 6)) 
x[indx[indx > 0]] <- 1 
x 
## [1] 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 

O

indx <- apply(cbind(which(x == 1) - 6 , which(x == 1)), 1, function(x) x[1]:x[2]) 
x[indx[indx > 0]] <- 1 
x 
## [1] 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 

O

indx <- seq_len(6) 
indx <- sapply(which(x == 1), function(x) x - indx) 
x[indx[indx > 0]] <- 1 
x 
## [1] 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0

+1.Stavo cercando di usare la funzione apply sull'indice, ma non pensavo di estrarre gli indici usando apply e quindi assegnando tutti quelli a 1. Grazie per questa logica. – Anusha

5

Una soluzione completamente vettorizzati utilizzando filter:

as.integer(#turn logical value into numbers 
    as.logical(#coerce to logical --> 0 becomes FALSE, everything else TRUE 
    rev(#reverse order 
    filter(#linear filtering 
     c(rep(0, 6), #pad with zeros in the beginning to avoid NAs 
     rev(x)), #revers order of input vector 
      c(rep(1, 7)), sides=1 #y_i = x_i * 1 + x_(i-1) * 1 +...+ x_(i-6) * 1 
)[-(1:6)]))) #remove NA values 

#[1] 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0

(+1) Bella vettorizzazione. –

+0

Non viene utilizzato il filtro per il tipo di calcolo medio mobile? Potresti spiegare come funziona la funzione filtro in questo contesto? Grazie. – Anusha

+0

'filter' calcola una somma mobile (per valori passati o per una finestra su entrambi i lati). Se la somma mobile non è zero, la trasformo in 1. – Roland

Problemi correlati