使用Plyr从函数返回多个值

时间:2013-07-15 13:11:21

标签: r function dataframe plyr

我对R来说还是个新手,所以请把它当作它的价值。

我编写了一个带有4个参数并返回数据帧的函数。浓缩版本如下所示。

Advantage <- function(tRos, tTat, cRos, cTat){
  #case 1.1 tRos is lower
  if((tRos > 0 | cRos > 0) & cRos > tRos & cTat < tTat){
    tRosAd <- (cRos - tRos) * cTat * -1
    tTatAd <- (tTat - cTat) * tRos
    r <- c(tRosAd, tTatAd, 1.1)
  }
  else if((tRos > 0 | cRos > 0) & cRos < tRos & cTat > tTat){
    #case 1.2 tRos is higher
    r <- Advantage(cRos, cTat, tRos, tTat)
    r <- r * -1
    r[3] <- 1.2
  }
  r <- data.frame(rosAd = r[1], tatAd = r[2], cat = r[3])
  return(r)
}

然后我需要做的是按年份和sic代码对数据进行子集化,然后针对该数据运行该函数。

我做了哪些令人难以置信的丑陋,令人难以置信的缓慢,并且有效,但当然不是最好的方法。

bDf <- data.frame()
for (yr in unique(aDf$year)){
  #Subset years
  tmp <- subset(aDf, year == yr)
  for(sc in unique(tmp$sic2)){
    #subset sics
    tmp2 <- subset(tmp, sic2 == sc)
    medRos <- median(tmp2$ros)
    medTat <- median(tmp2$tat)
    for (gvk in unique(tmp2$gvkey)){
      #subset individual gvkeys in the sics
      tmp3 <- subset(tmp2, gvk == gvkey)
      x <- Advantage(tmp3$ros, tmp3$tat, medRos, medTat)
      x <- cbind(tmp3, x)
      bDf <- rbind(bDf, x)
    }
  }
}

我最初让函数返回一个列表然后尝试将该函数应用于数据框并返回列表,但它一直在砍掉最后一列。

看起来如下:

outPut <- Advantage(tmp2$ros, tmp2$tat, median(tmp2$ros), median(tmp2$tat))

如何纠正我的丑陋代码的任何建议将不胜感激。我有一种感觉,这可能是plyr包中的一行,但我还没弄明白。

数据如下所示:

      gvkey year   at   ni sic sales        roa        ros       tat sic2
17857  1266 1966 5.21 0.06 100  1.06 0.01151631 0.05660377 0.2034549   10
17858  1266 1967 5.78 0.31 100  1.28 0.05363322 0.24218750 0.2214533   10
17859  1266 1968 6.54 0.79 100  1.80 0.12079511 0.43888889 0.2752294   10
17860  1266 1969 6.77 0.22 100  1.88 0.03249631 0.11702128 0.2776957   10
17861  1266 1970 8.57 0.15 100  2.42 0.01750292 0.06198347 0.2823804   10
17862  1266 1971 9.02 0.18 100  3.09 0.01995565 0.05825243 0.3425721   10

每个gvkey对应一个独特的公司。我正在考虑中位数ros&amp;每年从每个部门(sic2)开始,并将该部门内的每家公司与该部门在某一年的中位数进行比较。

1 个答案:

答案 0 :(得分:0)

外部两个循环可以用一个ddply调用替换,而内部循环可以用第二个循环替换。我保留了tmp2tmp3个名称,以显示您在原始代码中对应的内容。

library("plyr")
bDf <- ddply(aDf, .(year, sic2), function(tmp2) {
  medRos <- median(tmp2$ros)
  medTat <- median(tmp2$tat)
  ddply(tmp2, .(gvkey), function(tmp3) {
    Advantage(tmp3$ros, tmp3$tat, medRos, medTat)
  })
})

Advantage函数存在问题:在案例1.2中,Advantage返回data.frame,但该块中的其余代码将其视为返回向量。此外,这两种情况并未涵盖所有可能性(例如,您提供的示例数据,都不满足案例标准)。如果你的Advantage函数正常工作(并返回带有相应列的data.frame),那么这就可以循环遍历你想要的子集。