2013-08-06 148 views
1

我有一個數據集,其中包含3只動物的飼養數據,包括動物的標記ID(1,2,3),類型(A,B)和數量(千克)在每個「膳食」給定進料的:R數據幀滿足唯一條件的值總和

Animal FeedType Amount(kg) 
Animal1  A   10 
Animal2  B   7 
Animal3  A   4 
Animal2  A   2 
Animal1  B   5 
Animal2  B   6 
Animal3  A   2 

利用這一點,我希望能夠以輸出低於該具有unique('Animal')作爲其行,unique('FeedType')作爲其列和累積進給量的矩陣(千克)在矩陣的相應單元中。

  A B 
Animal1 10 5 
Animal2 2 13 
Animal3 6 0 

我開始編碼如下循環使用兩種解決方案:

dataframe = read_delim(input_url, header=TRUE, sep = ";") 
animal_feed_matrix = matrix(0,nrow(unique('Animal')),nrow(unique('FeedType'))) 
for (i in 1:length(unique('Animal'))){ 
a= unique('Animal')[i] 
    for (j in 1:length(unique('FeedType'))){ 
    ft= unique('FeedType')[j] 
    animal_feed_matrix[i,j] = sum(dataframe [(dataframe ['Animal']==a & dataframe ['FeedType']==ft),'Amount(kg)']) 
    } 
} 

但我知道,這是解決問題的一個非常低效的方式,(加上上面的代碼需要完成才能工作)。我知道R有級別,因素,我覺得可以更優雅地解決問題。

P.S.:This question有點類似於我的,但即使我的問題的解決方案包含在內,它逃脫了我。

回答

1

在基礎R:

out <- with(mydf, tapply(Amount, list(Animal, FeedType), sum)) 

     A B 
Animal1 10 5 
Animal2 2 13 
Animal3 6 NA 

然後,改變NA0(如你的例子),只是做:

out[is.na(out)] <- 0 
+0

哇,這對於單行代碼來說非常強大,就像一個魅力一樣!只是一個簡單的問題:現在'out'矩陣太稀疏了,因爲我有太多的FeedType列,我怎樣才能省略那些少出現的FeedTypes比一定數量的時間?(例如,我想排除'out'中的列'FeedTypeA'如果在'mydf'它只發生一次) – Rhubarb

+0

@Berkan我可能會預處理原始數據幀,排除FeedTypes在運行'by'之前低於特定閾值。但是,你可以從結果矩陣中刪除列,像這樣:'out [,!colnames(out)==「A」,drop = FALSE]'(在大矩陣中'drop = FALSE'是不必要的,但是可以防止強制示例矩陣只有兩列到一個向量)。 – Thomas

1

你可以使用函數dcast()從庫reshape2

library(reshape2)  
dcast(df,Animal~FeedType,sum,value.var="Amount") 
    Animal A B 
1 Animal1 10 5 
2 Animal2 2 13 
3 Animal3 6 0 
+0

謝謝,但這些代碼給出了一個錯誤:[使用子部門作爲值列:使用value.var來覆蓋。 vaggregate中的錯誤(.value = value,.group = overall,.fun = fun.aggregate,: 找不到函數「.fun]。另外,在這一行代碼中,我指定'sum'是on Amount? – Rhubarb

+0

函數dcast()自動使用第三列(如果只有三個)來計算sum。更新示例以更一般的解決方法使用參數value.var =(顯示使用哪一列)。在你的會話總和用作一些變量。看到這個[SO問題](http://stackoverflow.com/questions/7082792/error-message-running-the-example-from-the-reshape2-help-page) –