plyr沿两个维度(ddply)

时间:2011-11-29 23:24:50

标签: list r dataframe plyr

我有一个看起来像这样的数据框(简化为说明):

date id value
d1 id1 v1
d2 id1 v2
d1 id2 v3
d2 id2 v4

我想通过id打破这一点,对每个id进行滚动回归(因此对于每个id将有N个回归),选择rsquared并将其组装回数据帧。我这样做的方法是:

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)

然后我将使用

重新组装所有内容
ldply(models, function(x) {summary(x)$r.squared})

这不起作用,因为models是列表列表,x是模型列表。但是,如果我的function(x)cat返回列表 - 将所有rsquared返回到列表中,我会收到错误,因为ldply期望function(x)返回原子结果。非常感谢帮助。

3 个答案:

答案 0 :(得分:2)

此R代码再现了问题:

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

这有效:

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

希望这能回答你的问题。

答案 1 :(得分:0)

你能不能做到

ldply(models, laply, function(x) {summary(x)$r.squared})

基本上,由于你的x是一个模型列表,所以再做一次。我不确定返回值是否正确,因为它不可重复。

答案 2 :(得分:0)

您可以尝试rapply这是lapply的递归版本。你可以试试这样的东西

rapply(models, function(model) summary(model)$r.squared)

这将只返回r.squared的向量,您将不得不重新创建数据框。