Tertunda pada rangkaian waktu yang dikelompokkan

10

Saya memiliki beberapa puluh ribu pengamatan yang ada dalam rangkaian waktu tetapi dikelompokkan berdasarkan lokasi. Sebagai contoh:

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

Saya ingin melihat apakah bulan x 's observationAmemiliki hubungan linier dengan bulan x +1 observationB.

Saya melakukan riset dan menemukan zoofungsi, tetapi tampaknya tidak memiliki cara untuk membatasi kelambatan berdasarkan kelompok. Jadi jika saya menggunakan kebun binatang dan tertinggal observationB1 baris, saya akan berakhir dengan lokasi A observationBsebagai lokasi B yang pertama observationB. Saya lebih suka memiliki yang pertama observationBdari setiap lokasi menjadi NAatau nilai yang jelas lainnya untuk menunjukkan "jangan sentuh baris ini".

Saya kira apa yang saya maksudkan adalah apakah ada cara bawaan untuk melakukan ini di R? Jika tidak, saya bayangkan saya bisa menyelesaikan ini dengan konstruksi loop standar. Atau apakah saya perlu memanipulasi data?

Aren Cambre
sumber

Jawaban:

23

Ada beberapa cara bagaimana Anda bisa mendapatkan variabel yang tertinggal dalam suatu grup. Pertama-tama Anda harus mengurutkan data, sehingga dalam setiap kelompok waktu diurutkan sesuai.

Pertama mari kita buat contoh data.frame:

> 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

Tentukan fungsi lag kami:

 lg <- function(x)c(NA, x[1:(length(x)-1)])
  1. Kemudian lag variabel dalam kelompok dapat dihitung menggunakan 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. Menggunakan ddplydari plyr paket :

    > 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. Versi lebih cepat menggunakan data.tabledari package 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. Menggunakan lagfungsi dari 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. Menggunakan lagfungsi dari 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
    

Dua pendekatan terakhir membutuhkan konversi dari data.frameke objek lain, meskipun Anda tidak perlu khawatir tentang penyortiran. Preferensi pribadi saya adalah yang terakhir, yang tidak tersedia saat menulis jawaban pada awalnya.

Pembaruan: Mengubah kode data.table untuk mencerminkan perkembangan paket data.table, ditunjukkan oleh @Hibernating.

Pembaruan 2: Menambahkan contoh dplyr .

mpiktas
sumber
Penjelasan hebat! Apakah ada paket / fungsi yang dapat menangani time series (panel) yang dikelompokkan dan panel tidak seimbang?
Helix123
Semua contoh kode akan bekerja untuk panel yang tidak seimbang. Untuk deret waktu yang tidak beraturan, konsep lag agak rumit, karena mungkin tidak ada untuk semua kelompok.
mpiktas
Anda dapat bertanya tentang kelambatan untuk deret waktu tidak teratur dalam stackoverflow. Jenis-jenis pertanyaan ini sekarang di luar topik dalam stats.SE.
mpiktas
2

@ mpiktas Hanya untuk menyebutkan secara singkat dua kesalahan kecil dalam versi 3 jawaban Anda. Pertama, frasa "versi lebih cepat" jelas ditinggalkan karena kesalahan. Kedua, kata ": =" telah terlewat dalam kode. Memperbaiki yang terakhir memperbaiki yang pertama: =)

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))

masukkan deskripsi gambar di sini

Hibernasi
sumber
2

Daripada melewati semua langkah tapplydan langkah tambahan, inilah cara yang lebih cepat:

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
sumber
2

Dengan dplyr

dt %>% group_by(location) %>% mutate(lvar=lag(var))
Matius
sumber
0

Dengan DataCombine:

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

Data juga perlu disortir. Gunakan slideBy=-1sebagai gantinya untuk keterlambatan.

kitsune
sumber