2012-12-07 8 views
8

Możliwe Duplikat:
Can `ddply` (or similar) do a sliding window?istnieje funkcję jak rollapply do data.frame

jest tam działają jak rollapply (standard R lub w opakowaniu CRAN), który działa na zasadzie data.frame, ale nie przekształca go w macierz. Aplikacja rollapply może być używana z data.frame, ale jeśli data.frame ma typy mieszane, to każde okno danych jest konwertowane na znak (macierz).

Wolę funkcję, która obsługuje szerokość na.pad, wyrównanie, itp podobnie jak rollapply

Przykład

Podjęcie jakichkolwiek data.frame z mieszanymi typami

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

Powiedzmy, że chcesz przetasować z rozmiarem okna 2. Pierwsza iteracja FUN jest wywoływana z data.frame, która obejmuje tylko wiersze 1 i 2 testu.

RollapplyThatRespectsDataFrame(... , FUN = function(x) { ... }) więc po pierwszej iteracji będzie ustawiony x = data.frame(Name = c("bob" , "jane") , Points = c(4 , 9))

drugiej iteracji jest data.frame z wierszy 2 i 3 test.

Zasadniczo ta nowa funkcja działa tak samo, jak rollapply, z tym wyjątkiem, że działa poprawnie z data.frames. Nie przekształca się w macierz.

+0

To [pojawił się wcześniej] (http: // sta ckoverflow.com/q/7225992/324364), ale nie sądzę, że kiedykolwiek miał satysfakcjonującą odpowiedź. – joran

+0

może być konieczne napisanie własnego =) – SFun28

+0

Jeśli tak, proszę udostępnij! – joran

Odpowiedz

8

Spróbuj:

> 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 

W odniesieniu do przykładu, który został dodany do kwestii Po dyskusji, takie funkcje mogą być laminowane na górnej rollapply stosując do indeksów wierszy:

> 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 

i tutaj jest trochę lepiej opakowany:

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

Działa dla przykładu, ale nie można go uogólnić na data.frame z numerycznym przeplatanym znakiem. – SFun28

+0

Po prostu zastąp '1: 2' indeksami lub odpowiadającym im wektorem logicznym kolumn numerycznych:' ix <- sapply (DF, is.numeric); replace (DF, ix, rollapply (DF [ix], 3, sum, fill = NA)) ' –

+0

To działa! Jest to dobre rozwiązanie, jeśli FUN wymaga tylko kolumn numerycznych. Kompletne rozwiązanie zapewnia dane.frame dla każdego okna, dzięki czemu wszystkie typy są zachowywane. Jest to prawidłowy scenariusz, w którym chcemy uzyskać dane liczbowe i dane dotyczące obu okien. – SFun28