Ini adalah tindak lanjut dari pertanyaan saya sebelumnya: Bagaimana cara mengekstrak n baris pertama per grup dan menghitung fungsi menggunakan subset itu?
Posting lain yang relevan juga: Cara mengekstrak n baris pertama per kelompok?
Saya memiliki data berikut:
set.seed(1)
dt1 <- data.table(ticker="aa",letters=sample(LETTERS,10^6,T),x=rnorm(2000,100,10),y=rnorm(2000,80,20))
dt2 <- data.table(ticker="aapl",letters=sample(LETTERS,10^6,T),x=rnorm(2000,100,10),y=rnorm(2000,80,20))
dt3 <- data.table(ticker="abc",letters=sample(LETTERS,10^6,T),x=rnorm(2000,100,10),y=rnorm(2000,80,20))
myList <- list(dt1,dt2,dt3)
Saya ingin menerapkan fungsi ke data ini pada indeks tertentu berdasarkan grup di mana output fungsi bergantung pada kerangka data yang disubset. Saya kemudian ingin mengelompokkan data.tabel yang dihasilkan dengan variabel pengelompokan yang berbeda dan mengambil cara sederhana.
Apakah saya ingin menghitung fungsi saya berdasarkan grup1 pada baris subset terlebih dahulu, rbindlist hasilnya, lalu menghitung mean berdasarkan grup2?
Atau apakah saya ingin rbindlist seluruh data saya terlebih dahulu, pilih baris subset terlebih dahulu, lalu hitung fungsi saya berdasarkan grup1 lalu hitung rata-rata berdasarkan grup2?
# data.table version of function
dt_calc_perf <- function(dt){
buy <- ifelse(dt$x > mean(dt$y),1,0)
dt$perf <- buy*(dt$x/dt$y-1)
return(dt)
}
# vector return version of function
calc_perf <- function(dt){
buy <- ifelse(dt$x > mean(dt$y),1,0)
perf <- buy*(dt$x/dt$y-1)
return(perf)
}
# which is faster?
# method 1
method1 <- function(){
res1 <- rbindlist(lapply(1:length(myList),
function(m) dt_calc_perf(myList[[m]][1:1000])))
res1 <- res1[,list('perf'=mean(perf),'tickers'=paste(ticker,collapse=',')),
by=letters]
}
# method 2
dt <- rbindlist(myList)
x <- dt[dt[,.I[1:1000],by=ticker]$V1]
method2 <- function(){
res2 <- x[,list('letters'=letters,'perf'= calc_perf(.SD)),by=ticker]
res2 <- res2[,list('perf'=mean(perf),'tickers'=paste(ticker,collapse=',')),
by=letters]
}
all.equal(method1(),method2())
[1] TRUE
dengan panjang(Daftar Saya) = 3:
microbenchmark(method1(),method2())
Unit: milliseconds
expr min lq mean median uq max neval
method1() 2.874678 2.976673 3.181134 3.031414 3.103259 10.266646 100
method2() 3.008534 3.150086 3.352862 3.215517 3.292495 9.901859 100
dengan panjang(Daftar Saya) = 12:
> myList <- list(dt1,dt2,dt3,dt1,dt2,dt3,dt1,dt2,dt3,dt1,dt2,dt3)
> microbenchmark(method1(),method2())
Unit: milliseconds
expr min lq mean median uq max neval
method1() 9.284757 9.655745 10.346527 9.786392 10.016470 17.044078 100
method2() 3.020508 3.176173 3.330252 3.239680 3.322644 9.895444 100
Sunting:::
Satu hal yang perlu diperhatikan adalah fungsi method
saya pada akhirnya akan dimasukkan ke dalam algoritma optimasi genetik di mana method
akan dipanggil berkali-kali. Tujuan saya adalah untuk dapat menghitung calc_perf
(yang pada kenyataannya jauh lebih kompleks: input dt
output vektor perf
) berdasarkan subset dan ticker
. Lalu kelompokkan hasil dt
dengan letters
dan hitung mean(perf)
.