plyr lungo due dimensioni (ddply)
Domanda
Ho un frame di dati che si presenta così (semplificate per l'esposizione):
date id value
d1 id1 v1
d2 id1 v2
d1 id2 v3
d2 id2 v4
desidero spezzare questa parte da id, eseguire una regressione rotola su ciascun id (quindi per ogni id ci saranno N regressioni), scegliere la rsquared e montare questo nuovo ad un dataframe. Il mio metodo per fare questo è stato:
roll_reg <- function(df) {
T <- with(df, min(nlen(xs_ret), nlen(xs_mkt), nlen(smb), nlen(hml), nlen(umd)))
OFFSET <- 3
themodels <- as.list(rep(NA, OFFSET))
#120 days rolling period
if (T>OFFSET) {
#the first OFFSET models are na
for (i in seq(OFFSET+1, T)) {
idx <- seq(i-OFFSET-1,i)
themodels[i] <- list(with(df,
lm(xs_ret[idx]~xs_mkt[idx]+smb[idx]+hml[idx]+umd[idx])))
}
return(themodels)
}
else { return(NA) }
}
models <- dlply(dt_df, "id", roll_reg)
Poi stavo per rimontare il tutto utilizzando
ldply(models, function(x) {summary(x)$r.squared})
Questo non funziona in quanto i modelli è una lista di liste, e x è un elenco di modelli. Tuttavia, se il mio function(x)
restituisce un elenco da cat
-zione tutte le rsquared in una lista ottengo un errore perché si aspetta ldply
function(x)
per restituire un risultato atomica. Aiuto sarebbe molto apprezzato.
Soluzione
Questo codice R viene riprodotto il problema:
library(plyr)
dat = data.frame(date = rep(paste("d", 1:100, sep = ""), length = 100),
id = rep(paste("id", 1:10, sep = ""), each = 100),
value = runif(100))
make.lm = function(input) {
lm1 = lm(value~date, input[1:50,])
lm2 = lm(value~date, input[1:50,])
return(list(lm1, lm2))
}
models = dlply(dat, c("id"), make.lm)
coefs = ldply(models, function(x) summary(x)$r.squared)
# Error in summary(x)$r.squared : $ operator is invalid for atomic vectors
Questo funziona:
models = dlply(dat, c("id"), make.lm)
coefs = ldply(models, function(x)
ldply(x, function(y)
return(data.frame(rsq = summary(y)$r.squared))))
coefs$id2 = rep(1:2, each = 2)
> head(coefs)
id rsq id2
1 id1 1 1
2 id1 1 1
3 id10 1 2
4 id10 1 2
5 id2 1 1
6 id2 1 1
Spero che questo risponde alla tua domanda.
Altri suggerimenti
Non potresti fare
ldply(models, laply, function(x) {summary(x)$r.squared})
In sostanza, poiché la vostra x
è un elenco dei modelli, fare un altro l * strati più di questo. Non sono sicuro che il valore di ritorno è giusto, perché non è riproducibile.
Si potrebbe provare rapply
che è una versione ricorsiva di lapply
. Si potrebbe provare qualcosa di simile
rapply(models, function(model) summary(model)$r.squared)
Questo restituisce solo un vettore di r.squared, e si dovrà ricreare il frame di dati.