2012-12-07 9 views
8

Eventuali duplicati:
Can `ddply` (or similar) do a sliding window?C'è una funzione come rollapply per data.frame

C'è una funzione simile rollapply (standard R o all'interno di un pacchetto CRAN), che opera su un data.frame, ma non lo converte in una matrice. rollapply può essere usato con un data.frame, ma se data.frame ha tipi misti allora ogni finestra di dati viene convertita in un carattere (matrice).

preferisco una funzione che supporta la larghezza, na.pad, allineare, ecc proprio come rollapply

Esempio

prendere qualsiasi data.frame con mixed-tipi

test = data.frame(Name = c("bob" , "jane" , "joe") , Points = c(4 , 9 , 1))

Diciamo che si desidera eseguire il rollover con la dimensione della finestra 2. La prima iterazione di FUN viene chiamata con un data.frame che include solo le righe 1 e 2 del test.

Così RollapplyThatRespectsDataFrame(... , FUN = function(x) { ... }) sulla prima iterazione fisserebbe x = data.frame(Name = c("bob" , "jane") , Points = c(4 , 9))

La seconda iterazione è un data.frame con righe 2 e 3 del test.

Fondamentalmente questa nuova funzione fa la stessa cosa di rollapply, tranne che funziona correttamente con data.frames. Non converte in matrice.

+0

Questo [è venuto prima] (http: // sta ckoverflow.com/q/7225992/324364) ma non penso che abbia mai avuto una risposta soddisfacente. – joran

+0

potrebbe dover scrivere il mio =) – SFun28

+0

Se lo fai, si prega di condividere! – joran

risposta

8

Prova questo:

> library(zoo) 
> DF <- data.frame(a = 1:10, b = 21:30, c = letters[1:10]) 
> replace(DF, 1:2, rollapply(DF[1:2], 3, sum, fill = NA)) 
    a b c 
1 NA NA a 
2 6 66 b 
3 9 69 c 
4 12 72 d 
5 15 75 e 
6 18 78 f 
7 21 81 g 
8 24 84 h 
9 27 87 i 
10 NA NA j 

Per quanto riguarda l'esempio che è stato aggiunto alla domanda, dopo qualche discussione, tale funzionalità possono essere stratificati in cima rollapply applicandolo agli indici di riga:

> lapply(as.data.frame(t(rollapply(1:nrow(test), 2, c))), function(ix)test[ix, ]) 
$V1 
    Name Points 
1 bob  4 
2 jane  9 

$V2 
    Name Points 
2 jane  9 
3 joe  1 

e qui è un po 'meglio:

rollapply.data.frame <- function(data, ..., fill = NULL, FUN, 
     simplify = function(x) do.call(rbind, x)) { 
    fill0 <- if (!is.null(fill)) NA 
    result <- lapply(
     as.data.frame(t(rollapply(1:nrow(data), ..., fill = fill0, FUN = c))), 
     function(ix) {if (all(is.na(ix))) fill else FUN(data[ix, ])} 
    ) 
    simplify(result) 
} 

> rollapply(test, 2, FUN = identity, simplify = identity) 
$V1 
    Name Points 
a bob  4 
b jane  9 

$V2 
    Name Points 
b jane  9 
c joe  1 

> rollapply(test, 2, FUN = identity, fill = NA, simplify = identity) 
$V1 
    Name Points 
a bob  4 
b jane  9 

$V2 
    Name Points 
b jane  9 
c joe  1 

$V3 
[1] NA 
+0

Funziona per l'esempio, ma non può essere generalizzato a un data.frame con numerico inframmezzato con il carattere. – SFun28

+0

Basta sostituire '1: 2' con gli indici o il vettore logico corrispondente delle colonne numeriche:' ix <- sapply (DF, is.numeric); replace (DF, ix, rollapply (DF [ix], 3, sum, fill = NA)) ' –

+0

Funziona! È una buona soluzione se FUN ha bisogno solo di colonne numeriche. La soluzione completa fornirebbe un data.frame per finestra in modo che tutti i tipi siano preservati. È uno scenario valido per volere sia dati numerici per finestra che dati di carattere. – SFun28

Problemi correlati