Verzögerung über eine gruppierte Zeitreihe

10

Ich habe einige Zehntausende von Beobachtungen, die in einer Zeitreihe liegen, aber nach Orten gruppiert sind. Zum Beispiel:

location date     observationA observationB
---------------------------------------
 A       1-2010   22           12
 A       2-2010   26           15
 A       3-2010   45           16
 A       4-2010   46           27
 B       1-2010   167          48
 B       2-2010   134          56
 B       3-2010   201          53
 B       4-2010   207          42

Ich möchte sehen , ob Monat x ‚s observationAjede lineare Beziehung mit Monat hat x + 1 ist observationB.

Ich habe einige Nachforschungen angestellt und eine zooFunktion gefunden, aber es scheint keine Möglichkeit zu geben, die Verzögerung nach Gruppen zu begrenzen. Wenn ich also den Zoo benutzen würde und observationBum eine Reihe zurückbleiben würde, würde ich den letzten Ort A observationBals den ersten Ort B haben observationB. Ich hätte lieber den ersten observationBvon einem Ort NAoder einen anderen offensichtlichen Wert, um anzuzeigen, dass "diese Zeile nicht berühren".

Ich denke, es geht mir darum, ob es in R eine eingebaute Möglichkeit gibt, dies zu tun. Wenn nicht, kann ich mir vorstellen, dass ich dies mit einem Standardschleifenkonstrukt erledigen kann. Oder muss ich die Daten überhaupt manipulieren?

Aren Cambre
quelle

Antworten:

23

Es gibt verschiedene Möglichkeiten, wie Sie eine verzögerte Variable innerhalb einer Gruppe erhalten können. Zunächst sollten Sie die Daten so sortieren, dass in jeder Gruppe die Zeit entsprechend sortiert ist.

Lassen Sie uns zuerst ein Beispiel data.frame erstellen:

> set.seed(13)
> dt <- data.frame(location = rep(letters[1:2], each = 4), time = rep(1:4, 2), var = rnorm(8))
> dt
  location time        var
1        a    1  0.5543269
2        a    2 -0.2802719
3        a    3  1.7751634
4        a    4  0.1873201
5        b    1  1.1425261
6        b    2  0.4155261
7        b    3  1.2295066
8        b    4  0.2366797

Definieren Sie unsere Verzögerungsfunktion:

 lg <- function(x)c(NA, x[1:(length(x)-1)])
  1. Dann kann die Verzögerung der Variablen innerhalb der Gruppe berechnet werden mit tapply:

     > unlist(tapply(dt$var, dt$location, lg))
        a1         a2         a3         a4         b1         b2         b3         b4 
        NA  0.5543269 -0.2802719  1.7751634         NA  1.1425261  0.4155261  1.2295066
  2. Verwenden ddplyvon Paket plyr :

    > ddply(dt, ~location, transform, lvar = lg(var))
      location time        var       lvar
    1        a    1 -0.1307015         NA
    2        a    2 -0.6365957 -0.1307015
    3        a    3 -0.6417577 -0.6365957
    4        a    4 -1.5191950 -0.6417577
    5        b    1 -1.6281638         NA
    6        b    2  0.8748671 -1.6281638
    7        b    3 -1.3343222  0.8748671
    8        b    4  1.5431753 -1.3343222  
  3. Schnellere Version mit data.tableaus dem Paket data.table

     > ddt <- data.table(dt)
     > ddt[,lvar := lg(var), by = c("location")]
         location time        var       lvar
    [1,]        a    1 -0.1307015         NA
    [2,]        a    2 -0.6365957 -0.1307015
    [3,]        a    3 -0.6417577 -0.6365957
    [4,]        a    4 -1.5191950 -0.6417577
    [5,]        b    1 -1.6281638         NA
    [6,]        b    2  0.8748671 -1.6281638
    [7,]        b    3 -1.3343222  0.8748671
    [8,]        b    4  1.5431753 -1.3343222
  4. Verwenden der lagFunktion aus dem Paket plm

     > pdt <- pdata.frame(dt)
     > lag(pdt$var)
       a-1        a-2        a-3        a-4        b-1        b-2        b-3        b-4 
        NA  0.5543269 -0.2802719  1.7751634         NA  1.1425261  0.4155261  1.2295066
  5. Verwenden der lagFunktion aus dem Paket dplyr

    > dt %>% group_by(location) %>% mutate(lvar = lag(var))        
    Source: local data frame [8 x 4]
    Groups: location        
      location time        var       lvar
    1        a    1  0.5543269         NA
    2        a    2 -0.2802719  0.5543269
    3        a    3  1.7751634 -0.2802719
    4        a    4  0.1873201  1.7751634
    5        b    1  1.1425261         NA
    6        b    2  0.4155261  1.1425261
    7        b    3  1.2295066  0.4155261
    8        b    4  0.2366797  1.2295066

Die letzten beiden Ansätze erfordern die Konvertierung von data.frameeinem anderen Objekt, obwohl Sie sich dann nicht um das Sortieren kümmern müssen. Meine persönliche Präferenz ist die letzte, die beim ersten Schreiben der Antwort nicht verfügbar war.

Update: Der data.table-Code wurde geändert, um die Entwicklungen des data.table-Pakets widerzuspiegeln, auf die @Hibernating hingewiesen hat.

Update 2: Hinzugefügt dplyr Beispiel.

mpiktas
quelle
Tolle Erklärung! Gibt es ein Paket / eine Funktion, die mit unregelmäßig beabstandeten gruppierten Zeitreihen (Panels) und unausgeglichenen Panels umgehen kann?
Helix123
Alle Codebeispiele würden für unsymmetrische Panels funktionieren. Für unregelmäßig verteilte Zeitreihen ist das Konzept der Verzögerung etwas kompliziert, da es möglicherweise nicht für alle Gruppen existiert.
mpiktas
Sie können im Stackoverflow nach Verzögerungen für unregelmäßige Zeitreihen fragen. Diese Art von Fragen ist in stats.SE jetzt nicht mehr zum Thema.
mpiktas
2

@ mpiktas Um nur zwei kleine Versehen in Version 3 Ihrer Antwort kurz zu erwähnen. Erstens wurde der Ausdruck "schnellere Version" eindeutig irrtümlich verwendet. Zweitens wurde das Wort ": =" im Code übersehen. Das Reparieren des letzteren behebt das erstere: =)

library(data.table);ddt <- data.table(dt)
f0<-function() plyr::ddply(dt,~location,transform,lvar=lg(var))
f1<-function() ddt[,transform(.SD,lvar=lg(var)),by=c("location")]
f2<-function() ddt[,lvar:=lg(var),by=location]
r0<-f0();r1<-f1();r2<-f2();all.equal(r0,r1,r2,check.attributes = FALSE)
boxplot(microbenchmark::microbenchmark(f0(),f1(),f2(),times=1000L))

Geben Sie hier die Bildbeschreibung ein

Winterschlaf
quelle
2

Anstatt alle tapplyund zusätzliche Schritte durchzugehen, ist hier ein schnellerer Weg:

dt<-data.frame(location=rep(letters[1:2],each=4),time=rep(1:4,2),var=rnorm(8))
lg<-function(x)c(NA,x[1:(length(x)-1)])
dt$lg <- ave(dt$var, dt$location, FUN=lg)
Anirban Sengupta
quelle
2

Mit dplyr

dt %>% group_by(location) %>% mutate(lvar=lag(var))
Matthew
quelle
0

Mit DataCombine:

library(DataCombine)
slide(df, Var="observationB", TimeVar="date", GroupVar="location", NewVar="lead.observationB", 
slideBy = 1, keepInvalid = FALSE, reminder = FALSE)

Daten müssen ebenfalls sortiert werden. Verwenden Sie slideBy=-1stattdessen für Verzögerungen.

Kitsune
quelle