2011-08-29 72 views
8

我使用以下代碼來概括我的數據,通過使化合物,複製和質譜進行分組。如何在沒有排序的情況下使用ddply()?

summaryDataFrame <- ddply(reviewDataFrame, .(Compound, Replicate, Mass), 
    .fun = calculate_T60_Over_T0_Ratio) 

一個不幸的副作用是,所得到的數據幀由那些字段排序。我想這樣做,並保持化合物,複製品和質量與原始數據框中的順序相同。有任何想法嗎?我試着向原始數據添加一個「Sorting」順序整數列,但是當然我不能在.variables中包含它,因爲我不想按'分組',所以它不會返回到summaryDataFrame。

感謝您的幫助。

+0

這與'write.table'無關;標題應該改變。 –

回答

11

這來了個plyr郵件列表而回(由@kohske不低於募集),這是由Peter Meil​​strup有限的情況下,提供了一個解決方案:

#Peter's version used a function gensym to 
# create the col name, but I couldn't track down 
# what package it was in. 
keeping.order <- function(data, fn, ...) { 
    col <- ".sortColumn" 
    data[,col] <- 1:nrow(data) 
    out <- fn(data, ...) 
    if (!col %in% colnames(out)) stop("Ordering column not preserved by function") 
    out <- out[order(out[,col]),] 
    out[,col] <- NULL 
    out 
} 

#Some sample data 
d <- structure(list(g = c(2L, 2L, 1L, 1L, 2L, 2L), v = c(-1.90127112738315, 
-1.20862680183042, -1.13913266070505, 0.14899803094742, -0.69427656843677, 
0.872558638137971)), .Names = c("g", "v"), row.names = c(NA, 
-6L), class = "data.frame") 

#This one resorts 
ddply(d, .(g), mutate, v=scale(v)) #does not preserve order of d 

#This one does not 
keeping.order(d, ddply, .(g), mutate, v=scale(v)) #preserves order of d 

請務必閱讀thread爲哈德利的關於爲什麼這個功能可能不夠普遍以至於無法捲入ddply的筆記,特別是它可能適用於您的情況,因爲您可能每個作品返回的行較少。

編輯,包括更普遍的情況下

如果ddply正在輸出的東西,是你不喜歡的順序進行排序的策略,你基本上有兩種選擇:指定在分裂變量所需的訂貨提前使用排序的因素,或在事實後手動對輸出進行排序。使用字符串,現在

d <- data.frame(x1 = rep(letters[1:3],each = 5), 
       x2 = rep(letters[4:6],5), 
       x3 = 1:15,stringsAsFactors = FALSE) 

例如,請考慮以下數據。 ddply將排序輸出,在這種情況下將需要默認的詞彙順序:如果得到的數據幀不能在「正確」爲了結束了

> ddply(d,.(x1,x2),summarise, val = sum(x3)) 
    x1 x2 val 
1 a d 5 
2 a e 7 
3 a f 3 
4 b d 17 
5 b e 8 
6 b f 15 
7 c d 13 
8 c e 25 
9 c f 27 


> ddply(d[sample(1:15,15),],.(x1,x2),summarise, val = sum(x3)) 
    x1 x2 val 
1 a d 5 
2 a e 7 
3 a f 3 
4 b d 17 
5 b e 8 
6 b f 15 
7 c d 13 
8 c e 25 
9 c f 27 

,有可能是因爲你真的想一些那些變量被排序的因素。假設我們真的很想x1x2下令像這樣:

d$x1 <- factor(d$x1, levels = c('b','a','c'),ordered = TRUE) 
d$x2 <- factor(d$x2, levels = c('d','f','e'), ordered = TRUE) 

現在,當我們使用ddply,所產生的排序將是爲我們打算:

> ddply(d,.(x1,x2),summarise, val = sum(x3)) 
    x1 x2 val 
1 b d 17 
2 b f 15 
3 b e 8 
4 a d 5 
5 a f 3 
6 a e 7 
7 c d 13 
8 c f 27 
9 c e 25 

這裏的故事的寓意是,如果ddply按照您不打算的順序輸出內容,這是一個好兆頭,您應該使用有序因子來分解您正在分解的變量。

+0

謝謝。這似乎對我「幾乎」起作用。如何將'.sortColumn'保存在函數的返回數據中? 'calculate_T60_Over_T0_Ratio < - 功能(DF){' '##進行檢查以確保正在被用於ratio'正確的時間點 't60Value = DF [其中(DF [, 「時間」] ==「如果(t0Value == 0),則結果爲' ' 't0Value = df [其中(df [,「Time」] ==「t = 0」),「Result」]' ' ){' '打印( 「錯誤 - 除以零!」)' '回報( 「NA」)' '}其他{' '回報(t60Value/t0Value)' '} ' '}' – James

+0

@James如果你想在結果中保留'.sortColumn',你可能只需從'keeping.order'中省略'out [,col] < - NULL'這一行。 – joran

+0

對不起,我不清楚。我收到'keeping.order'的錯誤,因爲'.sortColumn'沒有被我的函數返回(見上文)。 – James

1

我最終最終在原始數據框中添加了「索引」列。它由兩列pastedsep="_"組成。然後,我又創建了另一個數據框,該數據框僅由'索引'列的unique成員和一個計數器1:length(df)組成。我對返回排序數據幀的數據做了ddply()。然後以原始順序重新獲取數據,我做了merge()結果數據框和索引數據框(確保列的名稱相同,這使得這更容易)。最後,我做了order並刪除了無關的列。

不是一個優雅的解決方案,而是一個有效的解決方案。

感謝您的協助。它讓我思考着正確的方向。

相關問題