2012-01-18 15 views
9

que tiene un conjunto de datos similar a estaretraso general en el panel de datos de series temporales

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 

Quiero crear un desfase de Value, respetando 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 

lo he hecho muy ineficiente en un bucle

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 
     } 

pero esto es muy lento. Lo he visto usando by y tapply, pero no he averiguado cómo hacer que funcionen.

No creo que XTS o TS funcionen debido al elemento Usuario.

¿Alguna sugerencia?

+0

Creo que el paquete 'plm' tiene una implementación para este tipo de datos. – Seb

Respuesta

8

Puede usar ddply: corta un data.frame en pedazos y transforma cada pieza.

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

Funciona bien. Gracias Vincent. –

+0

La siguiente http://stackoverflow.com/questions/1296646/how-to-sort-a-dataframe-by-columns-in-r clasificación se puede hacer con 'arrange()' – pidosaurus

0

Del mismo modo, se podría utilizar 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)]))) 

La idea es exactamente el mismo: tomar valor, dividirlo por el usuario, a continuación, ejecutar una función en cada subgrupo. La lista no publicada la devuelve al formato vectorial.

0

aportaron a la Mesa así lo ordene usuario y la fecha, esto se puede hacer con zoo. El truco no es especificar un índice en este punto.

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

Para un panel sin missing obs this es una solución intuitiva:

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 tinta de la manera más fácil, especialmente teniendo en cuenta hacer más análisis, es convertir su marco de datos a la clase pdata.frame del paquete plm.

Después de la conversión de diff() y lag(), los operadores se pueden utilizar para crear diferencias y retrasos en el panel.

df<-pdata.frame(df,index=c("id","date") 
df<-transofrm(df, l_value=lag(value,1)) 
Cuestiones relacionadas