2012-01-18 13 views
9

Mam zestaw danych podobny do tegoogólnego opóźnienia w danych panelowych serii czasowych

User Date  Value 
A  2012-01-01 4 
A  2012-01-02 5 
A  2012-01-03 6 
A  2012-01-04 7 
B  2012-01-01 2 
B  2012-01-02 3 
B  2012-01-03 4 
B  2012-01-04 5 

Chcę stworzyć opóźnieniem Value, z poszanowaniem User.

User Date  Value Value.lag 
A  2012-01-01 4  NA 
A  2012-01-02 5  4 
A  2012-01-03 6  5 
A  2012-01-04 7  6 
B  2012-01-01 2  NA 
B  2012-01-02 3  2 
B  2012-01-03 4  3 
B  2012-01-04 5  4 

Zrobiłem to bardzo nieefektywnie w pętli

df$value.lag1<-NA 
levs<-levels(as.factor(df$User)) 
levs 
    for (i in 1:length(levs)) { 
    temper<- subset(df,User==as.numeric(levs[i])) 
    temper<- rbind(NA,temper[-nrow(temper),]) 
df$value.lag1[df$User==as.numeric(as.character(levs[i]))]<- temper 
     } 

Ale to jest bardzo powolny. Przyjrzałem się używaniu by i tapply, ale nie doszedłem do wniosku, jak je uruchomić.

Nie sądzę, że XTS lub TS będą działać z powodu elementu User.

Wszelkie sugestie?

+0

Myślę, że pakiet 'plm' ma implementację dla tego typu danych. – Seb

Odpowiedz

8

Można użyć ddply: wycina on element data.frame na kawałki i przekształca każdy element.

d <- data.frame( 
    User = rep(LETTERS[1:3], each=10), 
    Date = seq.Date(Sys.Date(), length=30, by="day"), 
    Value = rep(1:10, 3) 
) 
library(plyr) 
d <- ddply( 
    d, .(User), transform, 
    # This assumes that the data is sorted 
    Value = c(NA, Value[-length(Value)]) 
) 
+0

Działa dobrze. Dzięki, Vincent. –

+0

Po http://stackoverflow.com/questions/1296646/how-to-sort-a-dataframe-by-columns-in-r- sortowanie można wykonać za pomocą 'arrange()' – pidosaurus

0

Podobnie, można użyć tapply

# Create Data 
user = c(rep('A',4),rep('B',4)) 
date = rep(seq(as.Date('2012-01-01'),as.Date('2012-01-04'),1),2) 
value = c(4:7,2:5) 
df = data.frame(user,date,value) 
# Get lagged values 
df$value.lag = unlist(tapply(df$value, df$user, function(x) c(NA,x[-length(df$value)]))) 

idea jest taka sama: wziąć wartość, podzielić go przez użytkownika, a następnie uruchomić funkcję dla każdego podzbioru. Lista unlist przywraca ją do formatu wektorowego.

0

Pod warunkiem, że tabela została zamówiona przez użytkownika i datę, można to zrobić za pomocą zoo. Sztuczka polega nie na określaniu indeksu w tym momencie.

library(zoo) 
df <-read.table(text="User Date Value 
A 2012-01-01 4 
A 2012-01-02 5 
A 2012-01-03 6 
A 2012-01-04 7 
B 2012-01-01 2 
B 2012-01-02 3 
B 2012-01-03 4 
B 2012-01-04 5", header=TRUE, as.is=TRUE,sep = " ") 

out <-zoo(df) 

Value.lag <-lag(out,-1)[out$User==lag(out$User)] 
res <-merge.zoo(out,Value.lag) 
res <-res[,-(4:5)] # to remove extra columns 

    User.out Date.out Value.out Value.Value.lag 
1 A  2012-01-01 4   <NA>   
2 A  2012-01-02 5   4    
3 A  2012-01-03 6   5    
4 A  2012-01-04 7   6    
5 B  2012-01-01 2   <NA>   
6 B  2012-01-02 3   2    
7 B  2012-01-03 4   3    
8 B  2012-01-04 5   4 
1

Na panelu bez brakujące obs to intuicyjne rozwiązanie:

df <- data.frame(id = c(1, 1, 1, 1, 1, 2, 2), 
       date = c(1992, 1993, 1991, 1990, 1994, 1992, 1991), 
       value = c(4.1, 4.5, 3.3, 5.3, 3.0, 3.2, 5.2)) 

df<-df[with(df, order(id,date)), ] # sort by id and then by date 
df$l_value=c(NA,df$value[-length(df$value)]) # create a new var with data displaced by 1 unit 
df$l_value[df$id != c(NA, df$id[-length(df$id)])] =NA # NA data with different current and lagged id. 
df 

id date value l_value 
4 1 1990 5.3  NA 
3 1 1991 3.3  5.3 
1 1 1992 4.1  3.3 
2 1 1993 4.5  4.1 
5 1 1994 3.0  4.5 
7 2 1991 5.2  NA 
6 2 1992 3.2  5.2 
0

I th atrament najprościej, zwłaszcza biorąc pod uwagę dalszą analizę, to przekonwertować ramkę danych do klasy pdata.frame z pakietu plm.

Po konwersji z diff() i lag() można wykorzystać operatorów do tworzenia opóźnień i różnic między panelami.

df<-pdata.frame(df,index=c("id","date") 
df<-transofrm(df, l_value=lag(value,1)) 
Powiązane problemy