2009-11-23 15 views
9

uczę R i jestem ciekaw ... Potrzebuję funkcję, która wykonuje to:propagujących dane w wektorze

> 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 

i wyprodukowałem to jedno ... ale podejrzewam, że istnieje więcej R sposób, aby to zrobić.

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

Odpowiedz

14

Pakiet zoo posiada funkcję 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: Last Observation przeniesione; Ogólna funkcja zastępowania każdej "NA" ostatnią nie będącą "NA "przed nią.

Zobacz kod źródłowy funkcji na.locf.default, nie potrzebuje ona for -loop.

+0

i jego parametr fromLast rozwiązuje pytanie symetryczne! (Czytam kod na.locf.R teraz i jest pełno rzeczy wartych przeczytania) – mariotomo

+0

interesujące źródło. Dodaję inną odpowiedź, destylowaną z twojej i z biblioteki zoo. – mariotomo

13

robię jakąś minimalną kopia & pastę z biblioteki zoo (dzięki ponownie RCS za naprowadzenie mnie na to) i to jest to, co naprawdę potrzebne:

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

dla zabawy (ponieważ jest wolniejszy niż fillInTheBlanks), oto wersja na.locf powołując się na rle funkcję:

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

np

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

Kolejna prosta odpowiedź. Ten dba o pierwszą wartość NA. To ślepy zaułek, więc moje statystyki pętli z indeksu 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) 
}