2013-07-15 135 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),那麼這就給出了你想要的子集的循環方式。