2009-11-23 1 views
9

j'apprends R et je suis curieux ... je besoin d'une fonction qui fait cela:propageant des données dans un vecteur

> fillInTheBlanks(c(1, NA, NA, 2, 3, NA, 4)) 
[1] 1 1 1 2 3 3 4 
> fillInTheBlanks(c(1, 2, 3, 4)) 
[1] 1 2 3 4 

et je produit celui-ci ... mais je pense qu'il ya un plus R façon de le faire.

fillInTheBlanks <- function(v) { 
    ## replace each NA with the latest preceding available value 

    orig <- v 
    result <- v 
    for(i in 1:length(v)) { 
    value <- v[i] 
    if (!is.na(value)) 
     result[i:length(v)] <- value 
    } 
    return(result) 
} 

Répondre

14

Package zoo a une fonction na.locf():

R> library("zoo") 
R> na.locf(c(1, 2, 3, 4)) 
[1] 1 2 3 4 
R> na.locf(c(1, NA, NA, 2, 3, NA, 4)) 
[1] 1 1 1 2 3 3 4 

na.locf: Dernière observation reportée; Fonction générique pour remplacer chaque 'NA' par le plus récent non-'NA 'précédent. Voir le code source de la fonction na.locf.default, il n'a pas besoin d'un for -loop.

+0

et son paramètre fromLast résout la question symétrique! (Je lis le code de na.locf.R maintenant et il est plein de choses à lire) – mariotomo

+0

source intéressante. J'ajoute une autre réponse, distillée de la vôtre et de la bibliothèque du zoo. – mariotomo

13

Je fais un peu de pâte copie & minimale de la bibliothèque de zoo (merci encore rcs pour moi le pointant) et c'est ce que je avais vraiment besoin:

fillInTheBlanks <- function(S) { 
    ## NA in S are replaced with observed values 

    ## accepts a vector possibly holding NA values and returns a vector 
    ## where all observed values are carried forward and the first is 
    ## also carried backward. cfr na.locf from zoo library. 
    L <- !is.na(S) 
    c(S[L][1], S[L])[cumsum(L)+1] 
} 
2

Juste pour le plaisir (car il est plus lent que fillInTheBlanks), voici une version de na.locf reposant sur la fonction rle:

my.na.locf <- function(v,fromLast=F){ 
    if(fromLast){ 
    return(rev(my.na.locf(rev(v)))) 
    } 
    nas <- is.na(v) 
    e <- rle(nas) 
    v[nas] <- rep.int(c(NA,v[head(cumsum(e$lengths),-1)]),e$lengths)[nas] 
    return(v) 
} 

par exemple

v1 <- c(3,NA,NA,NA,1,2,NA,NA,5) 
v2 <- c(NA,NA,NA,1,7,NA,NA,5,NA) 

my.na.locf(v1) 
#[1] 3 3 3 3 1 2 2 2 5 

my.na.locf(v2) 
#[1] NA NA NA 1 7 7 7 5 5 

my.na.locf(v1,fromLast=T) 
#[1] 3 1 1 1 1 2 5 5 5 

my.na.locf(v2,fromLast=T) 
#[1] 1 1 1 1 7 5 5 5 NA 
0

une autre réponse simple. Celui-ci prend soin de la 1ère valeur étant NA. C'est une impasse donc mes statistiques de boucle de l'index 2.

my_vec <- c(1, NA, NA, 2, 3, NA, 4) 
fill.it <- function(vector){ 
    new_vec <- vector 
    for (i in 2:length(new_vec)){ 
    if(is.na(new_vec[i])) { 
     new_vec[i] <- new_vec[i-1] 
    } else { 
     next 
    } 
    } 
    return(new_vec) 
}