2013-07-15 139 views
0

我对R相当陌生,所以把它看作是值得的。从函数返回多个值与Plyr

我写了一个函数,它需要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对应一个独特的公司。我将每个行业(sic2)的每个行业的中位数(sic2),并将该行业内的每家公司与该行业在某一年的中位数进行比较。

+0

你可以提供一些示例数据来处理...因为它,我假设每个子集都是1行或更多行,因此你的'Advantage'函数的'if'语句可能不会做你认为它会。 。 – Justin

+0

确定这是过去45年来每家上市公司的销售回报率和资产周转率数据。 gvkeys代表独特的公司。 – rwdvc

+0

为什么你不尝试在较小规模上重新创建你的问题。显然,速度在这一点上可能不会成为问题,但至少其他人可以看到清晰的输入和期望输出示例,并且能够帮助您解决问题。 – A5C1D2H2I1M1N2O1R2T1

回答

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),那么这就给出了你想要的子集的循环方式。